题解:P11030 『DABOI Round 1』Blessings Repeated
节选自:DP做题记录(三)(2025.4.5 - 2025.4.19)
由于 \(m\) 小的可怜,我们考虑把 \(T\) 这个字符串拆分成若干个子串,分别放入这 \(k\) 个重复的 \(S\) 中,然后就可以用组合数计算了。
那么问题就转变成了求出 \(T\) 的所有字串在 \(S\) 中作为子序列的出现次数。我们把 \(T_{[l, r]}\) 单独抽出来,设 \(dp_{i, j}\) 表示 \(S\) 的前 \(i\) 个字符中 \(T_{l, j}\) 出现的次数,那么如果 \(S_i = T_j\),就可以把 \(dp_{i - 1, j - 1}\) 的值加进来,否则就只能赋值为 \(dp_{i - 1, j}\),因此
其中初值为 \(dp_{0, 0} = 1\),可以发现这个式子和背包类似,因此第二维倒序枚举可以除掉 \(j\) 这一维。于是我们在时间复杂度为 \(O(nm^3)\),空间复杂度为 \(O(n)\) 的情况下求出了 \(T\) 的所有字串在 \(S\) 中作为子序列的出现次数。
现在就比较好做了,我们将 \(T\) 划分成若干个段,设划分了 \(l\) 段,那么将这 \(l\) 段放入 \(k\) 个重复的 \(S\) 中就有 \(\displaystyle\binom kl\) 种方案,而这些方案的权值是这 \(l\) 段分别在 \(S\) 中作为子序列的出现次数的积,直接加入到答案中。由于 \(m\) 只有 \(10\),这部分的时间复杂度比较小,可以忽略不计,那么我们用 \(O(nm^3)\) 的时间复杂度完成了此题。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e3 + 9, M = 19, MOD = 998244353;
int k, dp[N], tim[M][M], inv[M], fac[M], n, m, ans;
char s[N], t[M];
vector <int> vec;
int qpow(int a, int b){
int res = 1;
while(b > 0){
if(b & 1)
res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
int binom(int a, int b){
if(b > a)
return 0;
__int128 res = 1;
for(int i = a; i >= a - b + 1; i--)
res = res * i % MOD;
return res * inv[b] % MOD;
}
void dfs(int now){
if(now == 0){
int l = 1, r, tmp = 1;
for(int i = 0; i < (int)vec.size(); i++){
r = l + vec[i] - 1;
tmp = tmp * tim[l][r] % MOD;
l = r + 1;
}
ans = (ans + tmp * binom(k, vec.size()) % MOD) % MOD;
return;
}
for(int i = 1; i <= now; i++){
vec.push_back(i);
dfs(now - i);
vec.pop_back();
}
}
signed main(){
scanf("%lld", &k);
scanf("%s", s + 1);
scanf("%s", t + 1);
n = strlen(s + 1);
m = strlen(t + 1);
fac[0] = 1;
for(int i = 1; i <= m; i++)
fac[i] = fac[i - 1] * i % MOD;
inv[m] = qpow(fac[m], MOD - 2);
for(int i = m - 1; i >= 0; i--)
inv[i] = inv[i + 1] * (i + 1) % MOD;
for(int l = 1; l <= m; l++){
for(int r = l; r <= m; r++){
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= n; i++)
for(int j = r; j >= l; j--)
if(t[j] == s[i])
dp[j - l + 1] = (dp[j - l + 1] + dp[j - l]) % MOD;
tim[l][r] = dp[r - l + 1];
}
}
dfs(m);
printf("%lld", ans);
return 0;
}
本文来自博客园,作者:Orange_new,转载请注明原文链接:https://www.cnblogs.com/JPGOJCZX/p/18834273

浙公网安备 33010602011771号