- 要肝出这道题,你需要知道这样一个(trick.)
- 如果你要求对于一个什么东西求出现次数的平方,等价于同时进行两次操作,计算过程可以匹配的方案数。
- 这个(trick)可以去某次神仙(yyb)的暑假一次(noip)模拟赛学一下。
话说(yyb)那一次是真的毒瘤。话说神仙(fdf)当场爆切。
- 那么$ ∑A_i^2$,可以看成取两次得到了相同的串的方案数。
- 这样就很套路了,朴素想法设(f_{i,j,p,q})表示第一次(a)串在(i),(b)串在(j)位置,第二次(a)串在(p),(b)串在(q)位置。
- 很显然(i+j=p+q),那么后面一维度就省掉了,设(f_{i,j,k})表示总长度为(i),第一次(a)串在(j),第二次(a)串在(k)的方案数。
- 随便讨论转移一下即可,初始(f_{0,0,0}=1),复杂度(O(n^3))。
#include<bits/stdc++.h>
#define R register int
using namespace std;
const int N=601;
const int mod=1024523;
int n,m,f[2][N][N];char A[N],B[N];
void add(R &x,R y){x=(x+y>=mod?x+y-mod:x+y);}
int main(){
cin>>n>>m,scanf("%s",A+1),scanf("%s",B+1);
reverse(A+1,A+n+1),reverse(B+1,B+m+1);
R now=1,pre=0;f[now][0][0]=1;
for(R len=1;len<=n+m;++len){
now^=1,pre^=1;
for(R i=max(0,len-m);i<=min(n,len);++i)
for(R j=max(0,len-m);j<=min(n,len);++j)
f[now][i][j]=0;
for(R i=max(0,len-m);i<=min(n,len);++i){
for(R j=max(0,len-m);j<=min(n,len);++j){
R p=len-i,q=len-j;
if(i&&j&&A[i]==A[j])add(f[now][i][j],f[pre][i-1][j-1]);
if(i&&q&&A[i]==B[q])add(f[now][i][j],f[pre][i-1][j]);
if(p&&j&&B[p]==A[j])add(f[now][i][j],f[pre][i][j-1]);
if(p&&q&&B[p]==B[q])add(f[now][i][j],f[pre][i][j]);
}
}
}
cout<<f[now][n][n]<<endl;
return 0;
}