Challenge: Unfriendly Numbers
Subdomeniu: Number Theory (number-theory)
Scor cont: 80.0 / 80
Submission status: Accepted
Submission score: 1.0
Submission ID: 464759939
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/unfriendly-numbers/problem
Cerinta
Given $1$ *friendly* number and $n$ *unfriendly* numbers, determine how many numbers are divisors of the friendly number but *not* the unfriendly numbers.
Input Format
The first line contains $2$ space-separated integers, $n$ (the number of unfriendly numbers) and $f$ (the friendly number), respectively.
The second line contains $n$ space-separated unfriendly numbers.
Output Format
Print the the number of unique divisors of $f$ (i.e.: divisors that are not shared with those of the unfriendly numbers) as a single integer.
Constraints
- $1 \le n \le 10^6$
- $1 \le f \le 10^{13}$
- $1 \le \textit{unfriendly numbers} \le 10^{18}$
Cod sursa
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
int64 f;
cin >> n >> f;
// Factorize f.
vector<pair<int64, int>> pf;
int64 x = f;
for (int64 p = 2; p * p <= x; ++p) {
if (x % p == 0) {
int e = 0;
while (x % p == 0) {
x /= p;
++e;
}
pf.push_back({p, e});
}
}
if (x > 1) pf.push_back({x, 1});
// Generate all divisors of f.
vector<int64> divisors;
function<void(int, int64)> genF = [&](int idx, int64 cur) {
if (idx == (int)pf.size()) {
divisors.push_back(cur);
return;
}
auto [p, e] = pf[idx];
int64 val = 1;
for (int i = 0; i <= e; ++i) {
genF(idx + 1, cur * val);
val *= p;
}
};
genF(0, 1);
unordered_set<int64> gset;
gset.reserve(n * 2 + 1);
for (int i = 0; i < n; ++i) {
int64 u;
cin >> u;
int64 g = std::__gcd(u, f);
gset.insert(g);
}
// Mark bad divisors: divisors of any g in gset.
unordered_set<int64> bad;
bad.reserve(divisors.size() * 2 + 1);
for (int64 g : gset) {
// factor exponents of g w.r.t. f's primes
vector<int> eg(pf.size(), 0);
int64 t = g;
for (int i = 0; i < (int)pf.size(); ++i) {
int64 p = pf[i].first;
while (t % p == 0) {
t /= p;
++eg[i];
}
}
function<void(int, int64)> genG = [&](int idx, int64 cur) {
if (idx == (int)pf.size()) {
bad.insert(cur);
return;
}
int64 p = pf[idx].first;
int64 val = 1;
for (int i = 0; i <= eg[idx]; ++i) {
genG(idx + 1, cur * val);
val *= p;
}
};
genG(0, 1);
}
long long ans = (long long)divisors.size() - (long long)bad.size();
cout << ans << '\n';
return 0;
}
HackerRank Number Theory – Unfriendly Numbers
