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; }