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.
Treat the operation as an integer row operation. It is not about simulating plus/minus spam; it is about what integer combinations each position can absorb from positions before it.
For a subarray starting at , the value at position can be changed to exactly numbers congruent to modulo .
If every element after is divisible by , then the whole subarray can be made constant, so . The first element that is not divisible by is the only one that can create the main gap.
Let be the first index after with . Then for every is .
So for each , find the first non-multiple of to its right. Use a gcd sparse table: divides every value in a range iff it divides the gcd of that range. Then binary search the first bad position.
What the operation really does
The operation
is an integer row operation. Repeating adjacent row operations lets us add any integer combination of earlier original values into a later position.
So for a fixed subarray
the final value at position can be any integer of the form
That means the exact reachable condition is
The first value itself is fixed.
This is the big invariant. Once you have it, the problem stops being cursed.
The subarray formula
Fix the left endpoint . Let
First, suppose every later value in the subarray is divisible by . Then for every , we have
so we can choose the final value of every position to be exactly . Therefore
Now suppose there is some first index such that
Before , all values are divisible by , so all earlier final values are multiples of . Position must stay congruent to modulo .
Let
The closest a number with residue modulo can get to a multiple of is
So every valid final array has range at least .
That gives the lower bound. Now we need to show it is actually achievable.
If , use the interval
Otherwise, use
All positions before can be set to . Position can be set to the other endpoint of this interval.
After processing , the running gcd becomes
Since divides both and , it divides , so in particular
Every later modulus divides this , so every later modulus is also at most . Any integer interval of length contains a representative of every residue modulo any number . So every later value can also be placed inside the same interval.
Therefore the lower bound is tight:
for every .
So the entire subarray behavior is hilariously simple:
Summing over all subarrays
For each left endpoint , define as the first index greater than such that
If there is no such index, left endpoint contributes nothing.
Otherwise, every right endpoint
contributes the same value
There are
such right endpoints, so the total contribution of this is
Finding fast
We need the first position to the right that is not divisible by .
A range consists only of multiples of iff
So build a gcd sparse table. For a fixed , the predicate
is false before the first bad position and true from there onward. Binary search it.
Each gcd query is , each left endpoint uses queries, and building the sparse table costs .
Complexity
Per test case:
time and
memory.
The answer can exceed 64-bit, so use __int128. long long is not enough here; it gets cooked.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128_t;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void print128(i128 x) {
if (x == 0) {
cout << 0 << '\n';
return;
}
string s;
while (x > 0) {
s.push_back(char('0' + x % 10));
x /= 10;
}
reverse(s.begin(), s.end());
cout << s << '\n';
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<int> lg(n + 1);
for (int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
int K = lg[n] + 1;
vector<vector<ll>> st(K, vector<ll>(n));
st[0] = a;
for (int k = 1; k < K; k++) {
int len = 1 << k;
for (int i = 0; i + len <= n; i++) {
st[k][i] = gcd(st[k - 1][i], st[k - 1][i + (len >> 1)]);
}
}
auto range_gcd = [&](int l, int r) -> ll {
int k = lg[r - l + 1];
return gcd(st[k][l], st[k][r - (1 << k) + 1]);
};
i128 ans = 0;
for (int l = 0; l + 1 < n; l++) {
ll x = a[l];
if (range_gcd(l + 1, n - 1) % x == 0) continue;
int lo = l + 1, hi = n - 1;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (range_gcd(l + 1, mid) % x != 0) hi = mid;
else lo = mid + 1;
}
ll rem = a[lo] % x;
ll d = min(rem, x - rem);
ans += (i128)(n - lo) * d;
}
print128(ans);
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128_t;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void print128(i128 x) {
if (x == 0) {
cout << 0 << '\n';
return;
}
string s;
while (x > 0) {
s.push_back(char('0' + x % 10));
x /= 10;
}
reverse(s.begin(), s.end());
cout << s << '\n';
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<int> lg(n + 1);
for (int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
int K = lg[n] + 1;
vector<vector<ll>> st(K, vector<ll>(n));
st[0] = a;
for (int k = 1; k < K; k++) {
int len = 1 << k;
for (int i = 0; i + len <= n; i++) {
st[k][i] = gcd(st[k - 1][i], st[k - 1][i + (len >> 1)]);
}
}
auto range_gcd = [&](int l, int r) -> ll {
int k = lg[r - l + 1];
return gcd(st[k][l], st[k][r - (1 << k) + 1]);
};
i128 ans = 0;
for (int l = 0; l + 1 < n; l++) {
ll x = a[l];
if (range_gcd(l + 1, n - 1) % x == 0) continue;
int lo = l + 1, hi = n - 1;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (range_gcd(l + 1, mid) % x != 0) hi = mid;
else lo = mid + 1;
}
ll rem = a[lo] % x;
ll d = min(rem, x - rem);
ans += (i128)(n - lo) * d;
}
print128(ans);
}
}