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.
Since all are positive, any beautiful pair must have . So you only need to count ordered-left-to-right pairs satisfying .
A direct nested loop is doomed: is too big. Instead, for a fixed left index , think of trying possible values of . If , then the only possible position is .
The annoying part is that can be huge. But if both and are large, then is very large too, and it cannot fit inside the distance .
Split values by a threshold . For pairs where the right value is small, enumerate that small value and check .
For pairs involving a large value, enumerate multiples of that large value to the left/right. Count each pair exactly once: small-left handles small right values, while large positions explicitly scan both directions.
The condition is
Because , the right side must be positive, so automatically . That is useful: no weird symmetric counting, no zero-distance nonsense.
A first rewrite is:
So if we fix and guess , then the position is forced to be exactly . The dumb version guesses every possible , but can be up to , so that is not directly fine.
The escape hatch is the usual square-root split. Pick a threshold around ; using is enough because .
We separate array values into:
Now count pairs without double-counting.
For every index :
If , enumerate only small possible right values . The only candidate right index is If and , then is beautiful.
This counts exactly the pairs whose left value is small and whose right value is small.
If , scan positions at distances that are multiples of :
This counts every pair where the current large value participates. Yes, both directions are needed: the large value might be on the left or on the right.
Why does this not double-count?
Complexity:
With , this is about , easily fine for .
Memory usage is . Edge cases like huge are harmless: their multiple scans stop immediately, because the first jump already leaves the array.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
const ll B = 500;
while (t--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
ll ans = 0;
for (int i = 0; i < n; i++) {
if (a[i] >= B) {
for (ll x = 1; i + a[i] * x < n; x++) {
if (a[i + a[i] * x] == x) ans++;
}
for (ll x = 1; i - a[i] * x >= 0; x++) {
if (a[i - a[i] * x] == x) ans++;
}
} else {
for (ll x = 1; x < B && i + a[i] * x < n; x++) {
if (a[i + a[i] * x] == x) ans++;
}
}
}
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
const ll B = 500;
while (t--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
ll ans = 0;
for (int i = 0; i < n; i++) {
if (a[i] >= B) {
for (ll x = 1; i + a[i] * x < n; x++) {
if (a[i + a[i] * x] == x) ans++;
}
for (ll x = 1; i - a[i] * x >= 0; x++) {
if (a[i - a[i] * x] == x) ans++;
}
} else {
for (ll x = 1; x < B && i + a[i] * x < n; x++) {
if (a[i + a[i] * x] == x) ans++;
}
}
}
cout << ans << '\n';
}
return 0;
}