Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Because every , the cost is just the number of increments you do. Try to first bound how large the answer can ever be.
The answer is at most : pick any two elements and increment each odd one until it becomes even. Two even numbers have gcd at least .
So the only possible answers are , , or . Answer happens exactly when two original numbers already share some prime factor.
Answer means you increment exactly one number, say to , and it must share a prime factor with some unchanged .
Factor all original numbers and store which primes appear. If any prime appears in two different numbers, print . Otherwise, factor every ; if any of its primes appeared in the original array, print . If neither happens, print .
The easy version has one massive simplification: every increment costs exactly . So we are not choosing between cheap and expensive elements. The cost is literally just "how many +1 moves did we do?"
Key bound
The answer is never more than .
Why? Pick any two indices. If both numbers are odd, increment both once and they become even. If one is already even, increment the odd one once. If both are already even, you needed moves. In all cases, after at most moves, those two chosen values are both divisible by , so their gcd is at least .
So the whole problem collapses to deciding between only three answers:
No hidden -move nonsense. The ceiling is .
When is the answer 0?
We need some pair with gcd greater than . That means the two numbers share at least one prime factor.
So factor every into its distinct prime factors. If any prime appears in two different array elements, then those two elements already share that prime, and the answer is .
Important detail: for one number like , prime should only be counted once for that number. We care about how many indices contain the prime, not how many times it appears inside one value.
When is the answer 1?
If the answer is , then exactly one number changes from to . The other number in the pair stays unchanged.
So we need some prime such that:
That is enough, because then .
After we have already ruled out answer , we can store all primes that appear in the original array. Then for every , factor it. If any of its prime factors appeared in the original array, answer .
You do not even need to subtract the current index from the frequency. A prime dividing cannot divide , because consecutive numbers are coprime. So if that prime appeared originally, it appeared in some other element. Clean little math trick, no drama.
Otherwise answer 2
If neither nor works, then by the earlier bound, must work. Just make two numbers even.
Algorithm
For each test case:
The maximum value we need to factor is , so a smallest-prime-factor sieve is perfect.
Complexity
Precompute smallest prime factors up to about once.
Each number is factored in roughly logarithmic time, so the total work is easily fine for .
Overall complexity: , where and is the total number of array elements.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXV = 200005;
vector<int> spf(MAXV);
void build_spf() {
for (int i = 0; i < MAXV; i++) spf[i] = i;
spf[0] = 0;
spf[1] = 1;
for (int i = 2; 1LL * i * i < MAXV; i++) {
if (spf[i] != i) continue;
for (ll j = 1LL * i * i; j < MAXV; j += i) {
if (spf[j] == j) spf[j] = i;
}
}
}
vector<int> prime_factors(int x) {
vector<int> res;
while (x > 1) {
int p = spf[x];
res.push_back(p);
while (x % p == 0) x /= p;
}
return res;
}
int main() {
setIO();
build_spf();
int t;
cin >> t;
vector<int> cnt(MAXV, 0);
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
for (int i = 0; i < n; i++) {
int unused;
cin >> unused;
}
vector<int> touched;
bool zero = false;
for (int x : a) {
for (int p : prime_factors(x)) {
if (cnt[p] == 0) touched.push_back(p);
cnt[p]++;
if (cnt[p] >= 2) zero = true;
}
}
int ans = 2;
if (zero) {
ans = 0;
} else {
for (int x : a) {
for (int p : prime_factors(x + 1)) {
if (cnt[p] > 0) ans = 1;
}
}
}
cout << ans << '\n';
for (int p : touched) cnt[p] = 0;
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXV = 200005;
vector<int> spf(MAXV);
void build_spf() {
for (int i = 0; i < MAXV; i++) spf[i] = i;
spf[0] = 0;
spf[1] = 1;
for (int i = 2; 1LL * i * i < MAXV; i++) {
if (spf[i] != i) continue;
for (ll j = 1LL * i * i; j < MAXV; j += i) {
if (spf[j] == j) spf[j] = i;
}
}
}
vector<int> prime_factors(int x) {
vector<int> res;
while (x > 1) {
int p = spf[x];
res.push_back(p);
while (x % p == 0) x /= p;
}
return res;
}
int main() {
setIO();
build_spf();
int t;
cin >> t;
vector<int> cnt(MAXV, 0);
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
for (int i = 0; i < n; i++) {
int unused;
cin >> unused;
}
vector<int> touched;
bool zero = false;
for (int x : a) {
for (int p : prime_factors(x)) {
if (cnt[p] == 0) touched.push_back(p);
cnt[p]++;
if (cnt[p] >= 2) zero = true;
}
}
int ans = 2;
if (zero) {
ans = 0;
} else {
for (int x : a) {
for (int p : prime_factors(x + 1)) {
if (cnt[p] > 0) ans = 1;
}
}
}
cout << ans << '\n';
for (int p : touched) cnt[p] = 0;
}
}