bzoj1566 [NOI2009]管道取珠
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1566
【题解】
考虑表示的实际意义,相当于我取两次球,得到方案完全相同的个数。
设$f_{i,j,k}$表示取了$i$个,第一种上面取$j$个,第二种上面取$k$个,随便转移。
复杂度$O(n^3)$。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e2 + 10; const int mod = 1024523; int f[2][M][M]; int nA, nB; char a[M], b[M]; inline void cadd(int &a, int b) { a += b; if(a >= mod) a -= mod; } int main() { cin >> nA >> nB; scanf("%s%s", a+1, b+1); reverse(a+1, a+nA+1); reverse(b+1, b+nB+1); int cur = 0, nxt = 1; f[cur][0][0] = 1; for (int i=0; i<nA+nB; ++i) { int end_num = min(nA, i); memset(f[nxt], 0, sizeof f[nxt]); for (int j=0, jj; j<=end_num; ++j) for (int k=0, kk; k<=end_num; ++k) if(f[cur][j][k]) { jj = i - j, kk = i - k; if(jj > nB || kk > nB) continue; if(a[j+1] == a[k+1]) cadd(f[nxt][j+1][k+1], f[cur][j][k]); if(b[jj+1] == a[k+1]) cadd(f[nxt][j][k+1], f[cur][j][k]); if(a[j+1] == b[kk+1]) cadd(f[nxt][j+1][k], f[cur][j][k]); if(b[jj+1] == b[kk+1]) cadd(f[nxt][j][k], f[cur][j][k]); } swap(cur, nxt); } cout << f[cur][nA][nA]; return 0; }