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.
For a fixed ordering, a drop at position means the first numbers have some gcd , and the next number is not divisible by . That divisibility condition is the whole game.
Forget ordering for a second. If you want a drop after exactly the chosen set , then all numbers in are divisible by , and at least one unused number is not divisible by .
For any divisor , the best you can do with prefix gcd exactly is to take all current numbers divisible by — but this only works if the gcd of all those divisible numbers is exactly .
So for a prefix of length , the answer is the maximum such that and . If , then every number is divisible by , so no next number can break the gcd.
When appending , only divisors of have their and gcd data changed. The only useful divisor that can become valid without dividing is the previous global gcd: if is not divisible by it, putting all old elements first gives a drop at .
Let the current multiset be a prefix of size . We need : the latest possible position where the prefix gcd can strictly decrease after some reordering.
What does a drop mean?
Suppose an ordering has a drop at position . Let
Then the next gcd is
This is smaller than exactly when is not divisible by . No magic, no weird ordering trick. Just divisibility doing its usual thing.
So we need to choose some first block of numbers whose gcd is , while leaving outside at least one number not divisible by .
The key divisor view
Fix some possible gcd value .
Only numbers divisible by can be placed in the first block. To maximize , we would like to take as many of them as possible.
Let:
If , then taking all numbers divisible by gives prefix gcd exactly . Great: we can make a first block of size .
If , then every current number divisible by is also divisible by that larger common gcd. Any subset is still stuck with a gcd divisible by that larger value, so gcd exactly is impossible. That is useless.
One more condition: we need a remaining number not divisible by . That is exactly
Therefore:
If no such exists, the answer is .
That formula is the whole problem. The rest is just maintaining it without doing something tragically slow.
Online prefix update
Process the array left to right. When a new value is appended, only divisors of change:
All other divisors keep the same count and same gcd.
Since answers never decrease, keep a running ans and only check newly improved candidates.
There is one subtle case: a divisor that does not divide might become valid because the prefix length increased. Which one matters?
Let be the gcd of the previous prefix. If is not divisible by , then we can put all previous elements first. Their gcd is , and breaks it, so we immediately get candidate .
For any smaller divisor of the previous global gcd, the gcd of all previous elements is still , not that smaller divisor, so it does not satisfy . So the previous global gcd is the only non-divisor-of- candidate we need. Nice little trap, but not that nasty once you stare at it.
Algorithm
Precompute all divisors up to .
For each test case:
cnt[d] and mgcd[d].global_gcd of the processed prefix.ans.global_gcd, update ans = max(ans, i-1).global_gcd.cnt[d],mgcd[d],mgcd[d] == d and cnt[d] < i, update ans with cnt[d].ans.The condition cnt[d] < i means not all current numbers are divisible by , so there is some number available to break the prefix gcd.
Why this is correct
First, any valid drop at position has prefix gcd . The first numbers are all divisible by , and the next number is not divisible by . Therefore , , and gcd exactly must be achievable. That requires . So every possible answer is covered by the formula.
Second, if some satisfies and , place all numbers divisible by first. Their gcd is exactly . Then place any number not divisible by next. The gcd strictly decreases right there, giving position . So every value in the formula is actually achievable.
Third, during an append, only divisors of the appended value can have changed divisor statistics. Old valid candidates stay valid, so the running answer keeps them. The only old invalid candidate that can become valid without being updated is the old global gcd, and only when the old global gcd does not divide the new value. That gives candidate . So the incremental update checks everything it needs and nothing dumb.
Complexity
Precomputing divisors costs for .
Each array element processes all of its divisors, so the total work is
which is easily fine here. Memory is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MAXA = 200000;
vector<vector<int>> divisors(MAXA + 1);
for (int d = 1; d <= MAXA; d++) {
for (int x = d; x <= MAXA; x += d) {
divisors[x].push_back(d);
}
}
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> cnt(n + 1, 0), mgcd(n + 1, 0);
int ans = 0;
int global_gcd = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
int old_gcd = global_gcd;
if (i > 1 && x % old_gcd != 0) {
ans = max(ans, i - 1);
}
global_gcd = (global_gcd == 0 ? x : gcd(global_gcd, x));
for (int d : divisors[x]) {
cnt[d]++;
mgcd[d] = (mgcd[d] == 0 ? x : gcd(mgcd[d], x));
if (mgcd[d] == d && cnt[d] < i) {
ans = max(ans, cnt[d]);
}
}
cout << ans << (i == n ? '\n' : ' ');
}
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MAXA = 200000;
vector<vector<int>> divisors(MAXA + 1);
for (int d = 1; d <= MAXA; d++) {
for (int x = d; x <= MAXA; x += d) {
divisors[x].push_back(d);
}
}
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> cnt(n + 1, 0), mgcd(n + 1, 0);
int ans = 0;
int global_gcd = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
int old_gcd = global_gcd;
if (i > 1 && x % old_gcd != 0) {
ans = max(ans, i - 1);
}
global_gcd = (global_gcd == 0 ? x : gcd(global_gcd, x));
for (int d : divisors[x]) {
cnt[d]++;
mgcd[d] = (mgcd[d] == 0 ? x : gcd(mgcd[d], x));
if (mgcd[d] == d && cnt[d] < i) {
ans = max(ans, cnt[d]);
}
}
cout << ans << (i == n ? '\n' : ' ');
}
}
}