分析:
看到
a
i
2
a_i^2
ai2懵逼了,这是要怎么求?
冷静下来用脚趾头想一想就知道是分别做两次,然后第一次和第二次分别选一组出来有多少组是一样的
那就可以设
d
p
[
k
]
[
i
]
[
j
]
dp[k][i][j]
dp[k][i][j]表示到第k个,第一次的上面管道取了i个,第二次的上面管道取了j个的方案数
方程式:(a是上面,b是下面)
i
f
(
a
[
i
−
1
]
=
=
a
[
j
−
1
]
)
d
p
[
k
]
[
i
]
[
j
]
+
=
d
p
[
k
−
1
]
[
i
−
1
]
[
j
−
1
]
if(a[i-1]==a[j-1]) dp[k][i][j]+=dp[k-1][i-1][j-1]
if(a[i−1]==a[j−1])dp[k][i][j]+=dp[k−1][i−1][j−1]
i
f
(
a
[
i
−
1
]
=
=
b
[
k
−
j
−
1
]
)
d
p
[
k
]
[
i
]
[
j
]
+
=
d
p
[
k
−
1
]
[
i
−
1
]
[
j
]
if(a[i-1]==b[k-j-1]) dp[k][i][j]+=dp[k-1][i-1][j]
if(a[i−1]==b[k−j−1])dp[k][i][j]+=dp[k−1][i−1][j]
i
f
(
b
[
k
−
i
−
1
]
=
=
a
[
j
−
1
]
)
d
p
[
k
]
[
i
]
[
j
]
+
=
d
p
[
k
−
1
]
[
i
]
[
j
−
1
]
if(b[k-i-1]==a[j-1]) dp[k][i][j]+=dp[k-1][i][j-1]
if(b[k−i−1]==a[j−1])dp[k][i][j]+=dp[k−1][i][j−1]
i
f
(
b
[
k
−
i
−
1
]
=
=
b
[
k
−
j
−
1
]
)
d
p
[
k
]
[
i
]
[
j
]
+
=
d
p
[
k
−
1
]
[
i
]
[
j
]
if(b[k-i-1]==b[k-j-1]) dp[k][i][j]+=dp[k-1][i][j]
if(b[k−i−1]==b[k−j−1])dp[k][i][j]+=dp[k−1][i][j]
MLE?滚动数组降维
Code:
#include<bits/stdc++.h>
#define mod 1024523
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=505;
int dp[2][N][N];
char a[N],b[N];
inline void add(int &x,int y){x+=y;if(x>=mod) x-=mod;}
int main(){
int n=read(),m=read();
scanf("%s%s",a,b);
reverse(a,a+n);
reverse(b,b+m);
dp[0][0][0]=1;int now=1;
for(int k=1;k<=n+m;k++){
int low=max(0,k-m),high=min(n,k);
for(int i=low;i<=high;i++)
for(int j=low;j<=high;j++) dp[now][i][j]=0;
for(int i=low;i<=high;i++)
for(int j=low;j<=high;j++){
if(i && j && a[i-1]==a[j-1]) add(dp[now][i][j],dp[now^1][i-1][j-1]);
if(i && k-j && a[i-1]==b[k-j-1]) add(dp[now][i][j],dp[now^1][i-1][j]);
if(k-i && j && b[k-i-1]==a[j-1]) add(dp[now][i][j],dp[now^1][i][j-1]);
if(k-i && k-j && b[k-i-1]==b[k-j-1]) add(dp[now][i][j],dp[now^1][i][j]);
}
now^=1;
}
cout<<dp[(n+m)&1][n][n];
return 0;
}