考察:dp动态规划,dp的优化:滚动数组
思路:
因为ai是组成第i个序列的方案数,那么ai^2是两个装置都取得第i个序列的
方案数。
共有四个维度,
i:第一个人在第一个管子里取的球数,
j:第一个人在第二个管子里取的球数,
k:第二个人在第一个管子里取的球数,
l:第二个人在第二个管子里取的球数。
由于数据限制,因此最多只能三维,那么因为对于每个人,球的总数为i+j,因此l=i+j-k。
同时滚动数组优化。 最开始now=0,
f[i][j][k]表示已经取了i颗珠子,第一个装置第一行取了j个珠子,
第二个装置第二行取了k个珠子,所得到的序列是一样的方案数。
那么状态转移方程为:
if(a[i+1]==a[k+1]) f[now1][j][k+1]=(f[now1][j][k+1]+x)%mod;//变了i ,所以now^1 对应的i和k1变了
if(a[i+1]==b[l+1]) f[now1][j][k]=(f[now1][j][k]+x)%mod;//变了i ,所以now^1 对应i变了
if(b[j+1]==a[k+1]) f[now][j+1][k+1]=(f[now][j+1][k+1]+x)%mod;//对应的j和k都变了
if(b[j+1]==b[l+1]) f[now][j+1][k]=(f[now][j+1][k]+x)%mod;//对应的j变了
**
- 代码如下
**:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 520;
const int mod = 1024523;
int f[2][N][N],n,m;//滚动数组
char a[N],b[N];
inline void solve(){
scanf("%d%d",&n,&m);
scanf("%s",a+1);
scanf("%s",b+1);
f[0][0][0]=1;
for(int i=0,now=0;i<=n;i++,now^=1){
for(int j=0;j<=m;j++){
for(int k=0;k<=n;k++){
int l=i+j-k;//第四维 对于每个人来说,球的总数是i+j,因此对于第二个人,他在第二个管子里取的球为i+j-k
if(l<0||l>m) continue;
int &x=f[now][j][k];//当前状态
//进行状态转移
if(a[i+1]==a[k+1]) f[now^1][j][k+1]=(f[now^1][j][k+1]+x)%mod;//变了i ,所以now^1 对应的i和k1变了
if(a[i+1]==b[l+1]) f[now^1][j][k]=(f[now^1][j][k]+x)%mod;//变了i ,所以now^1 对应i变了
if(b[j+1]==a[k+1]) f[now][j+1][k+1]=(f[now][j+1][k+1]+x)%mod;//对应的j和k都变了
if(b[j+1]==b[l+1]) f[now][j+1][k]=(f[now][j+1][k]+x)%mod;//对应的j变了
x=0;
}
}
}
printf("%d\n",f[!(n&1)][m][n]);//因为最开始是从now=0开始的,因此要非一下,!(n&1)
}
int main(){
int t;
t=1;
while(t--){
solve();
}
return 0;
}