连接时光 II
Mier_Samuelle · · 题解
任意连通块一定是一段连续区间。考虑反证:若不连续,则存在
限制是针对一段前缀的,考虑在状态中记录
- 若
p_{i+1}>j ,则p_{i+1} 不会影响第一个连通块,其贡献取决于前面比它大的数的个数;转移为
- 若
p_{i+1} \le j ,则p_{i+1} 会使所有连通块合并,转移为
做完上述转移后,若
答案为
:::success[Code]{open}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5010;
const int MOD = 998244353;
ll a[MAXN], f[MAXN][MAXN], pw[MAXN][MAXN];
int n;
string s;
void solve(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
cin >> s;
s = " " + s;
for (int i = 1; i <= n; i++){
pw[i][0] = 1;
for (int j = 1; j <= n; j++){
pw[i][j] = pw[i][j - 1] * a[i] % MOD;
}
for (int j = 1; j <= n; j++){
pw[i][j] = (pw[i][j] + pw[i][j - 1]) % MOD;
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= i; j++){
f[i][j] = 0;
}
}
f[1][1] = 1;
for (int i = 1; i < n; i++){
if (s[i] == '1'){
f[i][i] = f[i][i] * 2 % MOD;
}
for (int j = 1; j <= i; j++){
f[i + 1][j] = (f[i + 1][j] + f[i][j] * pw[i + 1][i - j] % MOD) % MOD;
f[i + 1][i + 1] = (f[i + 1][i + 1] + f[i][j] * ((pw[i + 1][i] - pw[i + 1][i - j] + MOD) % MOD) % MOD) % MOD;
}
}
if (s[n] == '1'){
f[n][n] = f[n][n] * 2 % MOD;
}
ll ans = 0;
for (int i = 1; i <= n; i++){
ans = (ans + f[n][i]) % MOD;
}
cout << ans << "\n";
return;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--){
solve();
}
return 0;
}
:::