Problem Author: | Fady Rafat (FADY) |
Prepared by: | Fady Rafat (FADY) |
Edited by: | Hasan Saleh (MathModel) |
Solution
General Idea: We need to count distinct stable arrays (no two adjacent elements equal) that can be formed by applying operations on the original array.
Key Observation:
When we apply the operation on two adjacent equal elements a_i = a_{i+1} = v, we replace them with a single element of value v + 1. This means we can "merge" adjacent blocks of equal values into higher values.
More formally, a contiguous subarray of identical values [v, v, \ldots, v] of length 2^k can be merged into a single element of value v + k.
DP Formulation:
Let = the leftmost starting index such that the subarray a[L[i][v] \ldots i] can be merged into value .
This can be computed as:
L[i][a[i]] = i (a single element merges to itself)
L[i][v] = L[L[i][v-1] - 1][v-1] if the subarray ending at that merges to v-1 can be preceded by another subarray that also merges to v-1
Let dp[i][v] = number of stable arrays ending at position with last element value .
Let = total number of stable arrays ending at position .
The transition is:
If L[i][v] = 0: dp[i][v] += 1 (the entire prefix merges to )
Otherwise: dp[i][v] += ans[L[i][v] - 1] - dp[L[i][v] - 1][v]
We subtract dp[L[i][v] - 1][v] to avoid two adjacent blocks with the same value (stability condition).
Finally:
The answer is ans[n-1].
Complexity Analysis:
computation: \mathcal{O}(n \cdot V) where V = 80 + \log_2(n) \approx 102.
computation: \mathcal{O}(n \cdot V).
Total per test case: \mathcal{O}(n \cdot V).
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int MAX_V = 102;
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
vector<vector<int>> L(n, vector<int>(MAX_V, -1));
vector<vector<long long>> dp(n, vector<long long>(MAX_V, 0));
vector<long long> ans(n, 0);
for (int i = 0; i < n; i++) {
L[i][a[i]] = i;
for (int v = a[i] + 1; v < MAX_V; v++) {
int right_start = L[i][v - 1];
if (right_start > 0) {
int left_start = L[right_start - 1][v - 1];
if (left_start != -1)
L[i][v] = left_start;
}
}
for (int v = 0; v < MAX_V; v++) {
int start = L[i][v];
if (start == -1) continue;
if (start == 0) {
dp[i][v] = (dp[i][v] + 1) % MOD;
} else {
long long ways = (ans[start - 1] - dp[start - 1][v] + MOD) % MOD;
dp[i][v] = (dp[i][v] + ways) % MOD;
}
ans[i] = (ans[i] + dp[i][v]) % MOD;
}
}
cout << ans[n - 1] << "\n";
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}