Description:
有兩種珠子,有兩個管道,每個管道里有一些珠子,每次可以從上面或下面取珠子構成序列,問構成相同序列的操作對數。
Solution:
考慮 表示當前取了 個珠子,第一個操作從上面取了 個,第二個操作從上面取了 個且構成序列相同的方案數, 即可。
這類題的套路是把平方轉化爲對數進行統計。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
int n, m;
int dp[2][maxn][maxn];
char s[maxn], t[maxn];
void u(int &x, int y) {
x = (x + y) % 1024523;
}
int main() {
scanf("%d%d%s%s", &n, &m, s + 1, t + 1);
reverse(s + 1, s + n + 1);
reverse(t + 1, t + m + 1);
dp[0][0][0] = 1;
for(int N = 0, pre = 0; N < n + m; ++N, pre ^= 1) {
memset(dp[pre ^ 1], 0, sizeof(dp[pre ^ 1]));
for(int i = 0; i <= N && i <= n; ++i) {
for(int j = 0; j <= N && j <= n; ++j) {
if(s[i + 1] == s[j + 1]) {
u(dp[pre ^ 1][i + 1][j + 1], dp[pre][i][j]);
}
if(s[i + 1] == t[N - j + 1]) {
u(dp[pre ^ 1][i + 1][j], dp[pre][i][j]);
}
if(t[N - i + 1] == s[j + 1]) {
u(dp[pre ^ 1][i][j + 1], dp[pre][i][j]);
}
if(t[N - i + 1] == t[N - j + 1]) {
u(dp[pre ^ 1][i][j], dp[pre][i][j]);
}
}
}
}
printf("%d\n", dp[(n + m) & 1][n][n]);
return 0;
}