Description
给定两个管道,任意取珠子,有 种情况,定义
为取
个珠子的方案数总和
现在要求
Solution
对于 ,考虑其意义,从函数合成的角度,可以理解为两个相同的过程相互合成,即两次从管道取珠相同的方案数,那么这个计数问题我们可以用
去解决了,考虑
为第一个管道取了
个,第二个管道取了
个,第三个管道取了
个,第四个管道取了
个,显然空间复杂度过高,考虑优化一下,
, 可以少一维枚举,然后呢,
只会和
有关系,所以滚动数组优化一下,答案为
, 最终空间复杂度
, 时间复杂度为
另外,这道题卡常,可以试试开 O3 还有减少取模次数去优化常数。
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
const int mod = 1024523;
int dp[2][1005][1005];
void fun(int &x) {
if(x >= mod) {
x %= mod;
}
}
char s[1005], t[1005];
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, m;
scanf("%d %d", &n, &m);
scanf("%s %s", s + 1, t + 1);
dp[0][0][0] = 1;
for(int i = 0; i <= n; i++) {
for(int j = 0; j <= m; j++) {
for(int k = 0; k <= min(n, i + j); k++) {
int l = i + j - k;
if(!i && !j && !k) {
dp[i & 1][j][k] = 1;
continue;
}
dp[i & 1][j][k] = 0;
if(i && k && s[i] == s[k]) {
dp[i & 1][j][k] += dp[(i + 1) & 1][j][k - 1];
fun(dp[i & 1][j][k]);
}
if(i && l && s[i] == t[l]) {
dp[i & 1][j][k] += dp[(i + 1) & 1][j][k];
fun(dp[i & 1][j][k]);
}
if(j && k && t[j] == s[k]) {
dp[i & 1][j][k] += dp[i & 1][j - 1][k - 1];
fun(dp[i & 1][j][k]);
}
if(j && l && t[j] == t[l]) {
dp[i & 1][j][k] += dp[i & 1][j - 1][k];
fun(dp[i & 1][j][k]);
}
}
}
}
cout << dp[n & 1][m][n] << "\n";
return 0;
} 
京公网安备 11010502036488号