[bzoj1566]管道取珠
貌似求 i 次方的问题都有一个套路就是将原操作序列复制一遍,然后i个操作中等价的数量就是原问题的答案了。
然后这题就没了。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=503;
int f[2][N][N];
char A[N],B[N];
int n,m;
const int mod=1024523;
bool legal(int a,int b) {
return a>=0&&a<=n&&b>=0&&b<=m;
}
void upd(int &A,int tmp) {
A+=tmp;
A=A>=mod?A-mod:A;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",A+1);
scanf("%s",B+1);
f[0][0][0]=1;
for(int t=1; t<=n+m; t++) {
int cur=t%2;
int pst=cur^1;
for(int i=0; i<=min(t,n); i++)
for(int j=0; j<=min(t,n); j++)
f[cur][i][j]=0;
for(int i=0; i<=min(t,n); i++) {
int upA=i,dnA=t-1-i;
if(legal(upA,dnA))for(int j=0; j<=min(t,n); j++) {
int upB=j,dnB=t-1-j;
if(legal(upB,dnB))if(f[pst][upA][upB]) {
int tmp=f[pst][upA][upB];
if(upA+1<=n&&dnB+1<=m&&A[upA+1]==B[dnB+1])upd(f[cur][upA+1][upB],tmp);
if(upA+1<=n&&upB+1<=n&&A[upA+1]==A[upB+1])upd(f[cur][upA+1][upB+1],tmp);
if(dnA+1<=m&&upB+1<=n&&B[dnA+1]==A[upB+1])upd(f[cur][upA][upB+1],tmp);
if(dnA+1<=m&&dnB+1<=m&&B[dnA+1]==B[dnB+1])upd(f[cur][upA][upB],tmp);
}
}
}
}
printf("%d\n",f[(n+m)%2][n][n]);
}