——(shallwe):这道题是(noipDay2T2)难度
好一个(Day2T2)难度啊,我觉得我可以退役了
平方和好像没有什么办法可以快速统计,于是考虑转化一下
我们可以将题意转化成这样
求有序对((A,B)),取法(A)可以和取法(B)得到相同的结果
也就是可以将题目抽象成一个人进行这个游戏两遍,能得到同样结果的方案数是多少
之后我们可以设计出这样的(dp)方程,(dp[i][j][k][p])表示第一次取从上面那个管道里取出了(i)个,从下面那个管道里取出了(j)个,第二次从上面那个管道取出(k)个,从第二个管道里取出(p)个,得到的结果相同的方案数
结果相同肯定得取出的数量相同,所以(i+j=k+p),于是(p)那一维可以不要了
同时我们还可用滚掉一维,进一步优化空间
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 505
const int mod=1024523;
int n,m,o;
char A[maxn],B[maxn];
char a[maxn],b[maxn];
int dp[2][maxn][maxn];
inline int qm(int a,int b)
{
int t=a+b;
if(t>mod) return t-mod;
return t;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",A+1);
scanf("%s",B+1);
for(re int i=1;i<=n;i++) a[i]=A[n-i+1];
for(re int j=1;j<=m;j++) b[j]=B[m-j+1];
dp[0][0][0]=1;
for(re int i=0;i<=n;i++,o^=1)
for(re int j=0;j<=m;j++)
for(re int k=0;k<=n;k++)
{
int p=i+j-k;
if(p<0||p>m) continue;
if(a[i+1]==a[k+1]) dp[o^1][j][k+1]=qm(dp[o^1][j][k+1],dp[o][j][k]);
if(b[j+1]==b[p+1]) dp[o][j+1][k]=qm(dp[o][j+1][k],dp[o][j][k]);
if(a[i+1]==b[p+1]) dp[o^1][j][k]=qm(dp[o^1][j][k],dp[o][j][k]);
if(b[j+1]==a[k+1]) dp[o][j+1][k+1]=qm(dp[o][j+1][k+1],dp[o][j][k]);
dp[o][j][k]=0;
}
std::cout<<dp[o][m][n];
return 0;
}