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.
Track the set of missing numbers, not the multiset of chosen values. The -mex only cares whether a number has appeared at least once. Duplicates are mostly noise.
For prefix , let . If the -mex is , then among numbers there are exactly missing numbers, and itself is missing.
Define as the first missing numbers after choosing . Then has size and its maximum is exactly .
Compare and . If , then is forced: it is with the old maximum removed. If , then one smaller missing number was removed instead.
Count the chain backwards. For an equal step , you must add one number not already in , giving choices. For a decreasing step, is forced, but can be any value outside , giving choices.
Let . For the empty prefix, the -mex is , so this is the natural fake previous value.
For prefix , we ask for the -mex where
With only chosen values, the -mex cannot be below , and because all are in , it cannot exceed . So every valid construction needs
Also, cannot increase. If the old missing list has as its -st element, then after one insertion and asking for the -th element, the answer is either the old -th missing number or still . Never larger. Thus we need
If either check fails, the answer is .
Source cross-check: official Codeforces tutorial implementation, https://codeforces.com/blog/entry/151886
For prefix , define as the set of the first missing numbers from after reading .
The condition says exactly:
This is the whole trick. We do not need the full missing set, only this front chunk.
Now compare one step. Put .
Before step , has size and maximum . After step , has size and maximum .
The maximum decreased, so the removed element from the tracked missing set must be the old maximum . Therefore is forced:
But the actual value only needs to avoid changing the first missing numbers. So can be any number not in .
Since and , the number of allowed values is
So a decreasing step contributes a factor of .
The maximum stayed the same, so step removed some missing number smaller than .
Counting this forward is annoying because future constraints decide which smaller values survive. So count the sets backwards. Starting from , to recover we add one number that is not already in .
Inside , there are exactly numbers smaller than , because has size and its maximum is . Among the numbers , the available choices are therefore
So an equal step contributes
That is the entire counting formula. Tiny, but it hides a slick reversal.
With , after validation:
All products are taken modulo .
Each test case is just one scan:
time and
extra memory, ignoring the input array. Across all tests this is , which is exactly what we want. No segment tree, no DP circus, no 2400-rated tax audit.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n + 1);
a[0] = n;
for (int i = 1; i <= n; i++) cin >> a[i];
bool ok = true;
for (int i = 1; i <= n; i++) {
if (a[i] < n - i || a[i] > n) ok = false;
if (a[i] > a[i - 1]) ok = false;
}
if (!ok) {
cout << 0 << '\n';
continue;
}
ll ans = 1;
for (int i = 1; i <= n; i++) {
ll ways;
if (a[i] == a[i - 1]) {
ways = a[i] - (n - i);
} else {
ways = i;
}
ans = ans * (ways % MOD) % MOD;
}
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n + 1);
a[0] = n;
for (int i = 1; i <= n; i++) cin >> a[i];
bool ok = true;
for (int i = 1; i <= n; i++) {
if (a[i] < n - i || a[i] > n) ok = false;
if (a[i] > a[i - 1]) ok = false;
}
if (!ok) {
cout << 0 << '\n';
continue;
}
ll ans = 1;
for (int i = 1; i <= n; i++) {
ll ways;
if (a[i] == a[i - 1]) {
ways = a[i] - (n - i);
} else {
ways = i;
}
ans = ans * (ways % MOD) % MOD;
}
cout << ans << '\n';
}
}