题意:
有
两
个
管
道
,
管
道
1
有
n
个
球
,
管
道
2
有
m
个
球
有两个管道,管道1有n个球,管道2有m个球
有两个管道,管道1有n个球,管道2有m个球
球
有
A
和
B
两
种
颜
色
球有A和B两种颜色
球有A和B两种颜色
从
A
或
B
分
别
取
球
,
可
能
有
C
(
n
+
m
,
n
)
种
方
案
从A或B分别取球,可能有C(n+m,n)种方案
从A或B分别取球,可能有C(n+m,n)种方案
这
些
方
案
中
可
能
有
取
出
球
序
列
相
同
的
这些方案中可能有取出球序列相同的
这些方案中可能有取出球序列相同的
假
设
总
共
有
k
种
不
同
的
球
序
列
,
a
i
为
每
种
的
方
案
数
假设总共有k种不同的球序列,a_i为每种的方案数
假设总共有k种不同的球序列,ai为每种的方案数
那
么
∑
i
=
1
k
a
i
=
C
(
n
+
m
,
n
)
那么\sum_{i=1}^k a_i=C(n+m,n)
那么∑i=1kai=C(n+m,n)
求
∑
i
=
1
k
a
i
2
m
o
d
1024523
求\sum_{i=1}^k a_i^2~mod ~1024523
求∑i=1kai2 mod 1024523
题解:
n
,
m
<
=
500
n,m<=500
n,m<=500
求
∑
i
=
1
k
a
i
可
以
直
接
得
出
求\sum_{i=1}^k a_i可以直接得出
求∑i=1kai可以直接得出
但
是
要
求
求
的
结
果
是
∑
i
=
1
k
a
i
2
但是要求求的结果是\sum_{i=1}^k a_i^2
但是要求求的结果是∑i=1kai2
如
果
这
道
题
(
n
+
m
)
比
较
小
,
可
以
考
虑
二
进
制
枚
举
如果这道题(n+m)比较小,可以考虑二进制枚举
如果这道题(n+m)比较小,可以考虑二进制枚举
对
于
每
种
进
行
平
方
求
和
,
但
是
这
里
n
,
m
太
大
,
肯
定
不
够
用
对于每种进行平方求和,但是这里n,m太大,肯定不够用
对于每种进行平方求和,但是这里n,m太大,肯定不够用
所
以
我
们
就
可
以
把
问
题
转
化
所以我们就可以把问题转化
所以我们就可以把问题转化
一
般
对
于
k
次
方
,
你
就
可
以
把
他
转
化
成
k
个
人
玩
这
个
游
戏
一般对于k次方,你就可以把他转化成k个人玩这个游戏
一般对于k次方,你就可以把他转化成k个人玩这个游戏
就
比
如
这
道
题
,
是
两
次
方
,
所
以
转
化
成
2
个
人
玩
这
个
游
戏
就比如这道题,是两次方,所以转化成2个人玩这个游戏
就比如这道题,是两次方,所以转化成2个人玩这个游戏
然
后
求
这
两
个
人
序
列
相
同
的
方
案
数
然后求这两个人序列相同的方案数
然后求这两个人序列相同的方案数
第
一
个
拿
到
这
个
序
列
的
方
案
数
是
a
i
,
第
二
个
人
是
b
i
第一个拿到这个序列的方案数是a_i,第二个人是b_i
第一个拿到这个序列的方案数是ai,第二个人是bi
那
么
两
个
人
同
时
拿
到
这
个
序
列
的
方
案
数
就
是
a
i
∗
b
i
那么两个人同时拿到这个序列的方案数就是a_i*b_i
那么两个人同时拿到这个序列的方案数就是ai∗bi
对
于
这
道
题
中
,
游
戏
相
同
,
初
始
相
同
,
所
以
a
i
=
=
b
i
对于这道题中,游戏相同,初始相同,所以a_i==b_i
对于这道题中,游戏相同,初始相同,所以ai==bi
所
以
现
在
需
要
考
虑
的
就
是
2
个
人
玩
这
个
游
戏
序
列
相
同
的
方
案
数
所以现在需要考虑的就是2个人玩这个游戏序列相同的方案数
所以现在需要考虑的就是2个人玩这个游戏序列相同的方案数
这
样
就
很
明
显
了
,
应
该
是
用
d
p
来
求
这样就很明显了,应该是用dp来求
这样就很明显了,应该是用dp来求
然
后
开
始
构
建
d
p
的
模
型
然后开始构建dp的模型
然后开始构建dp的模型
状
态
应
该
就
是
两
个
人
各
自
从
两
个
管
道
拿
的
球
序
列
相
同
的
方
案
状态应该就是两个人各自从两个管道拿的球序列相同的方案
状态应该就是两个人各自从两个管道拿的球序列相同的方案
d
p
[
i
]
[
j
]
[
k
]
[
l
]
表
示
第
一
个
人
从
管
道
1
拿
i
个
,
管
道
2
拿
j
个
dp[i][j][k][l]表示第一个人从管道1拿i个,管道2拿j个
dp[i][j][k][l]表示第一个人从管道1拿i个,管道2拿j个
第
二
个
人
从
管
道
1
拿
k
个
,
管
道
2
拿
l
个
两
人
序
列
相
同
的
方
案
第二个人从管道1拿k个,管道2拿l个两人序列相同的方案
第二个人从管道1拿k个,管道2拿l个两人序列相同的方案
但
是
四
维
D
P
不
论
时
间
空
间
都
不
允
许
但是四维DP不论时间空间都不允许
但是四维DP不论时间空间都不允许
考
虑
一
下
降
维
,
我
们
会
发
现
,
两
个
人
序
列
相
同
,
拿
的
个
数
肯
定
一
样
考虑一下降维,我们会发现,两个人序列相同,拿的个数肯定一样
考虑一下降维,我们会发现,两个人序列相同,拿的个数肯定一样
所
以
i
+
j
=
=
k
+
l
,
那
么
就
可
以
去
掉
l
这
一
维
所以i+j==k+l,那么就可以去掉l这一维
所以i+j==k+l,那么就可以去掉l这一维
然
后
考
虑
状
态
转
移
,
由
于
是
拿
的
个
数
然后考虑状态转移,由于是拿的个数
然后考虑状态转移,由于是拿的个数
我
们
考
虑
的
应
该
是
往
下
一
个
状
态
转
移
我们考虑的应该是往下一个状态转移
我们考虑的应该是往下一个状态转移
如
果
第
一
个
人
管
道
1
(
管
道
2
)
的
当
前
球
和
第
二
个
人
管
道
2
的
当
前
球
一
样
如果第一个人管道1(管道2)的当前球和第二个人管道2的当前球一样
如果第一个人管道1(管道2)的当前球和第二个人管道2的当前球一样
那
么
就
可
以
让
这
两
个
人
分
别
拿
相
同
球
,
并
得
到
当
前
状
态
的
贡
献
那么就可以让这两个人分别拿相同球,并得到当前状态的贡献
那么就可以让这两个人分别拿相同球,并得到当前状态的贡献
这
样
就
可
以
形
成
状
态
转
移
(
详
细
见
下
代
码
)
这样就可以形成状态转移(详细见下代码)
这样就可以形成状态转移(详细见下代码)
然
后
可
以
看
到
,
这
个
递
推
永
远
是
往
下
一
个
状
态
转
移
然后可以看到,这个递推永远是往下一个状态转移
然后可以看到,这个递推永远是往下一个状态转移
也
就
是
球
数
增
长
的
方
向
,
不
需
要
前
一
步
的
值
也就是球数增长的方向,不需要前一步的值
也就是球数增长的方向,不需要前一步的值
这
样
的
话
,
对
于
最
外
层
循
环
那
一
维
,
就
可
以
使
用
滚
动
数
组
这样的话,对于最外层循环那一维,就可以使用滚动数组
这样的话,对于最外层循环那一维,就可以使用滚动数组
最 后 得 到 d p [ n ] [ m ] [ n ] 即 可 最后得到dp[n][m][n]即可 最后得到dp[n][m][n]即可
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1024523;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n,m;
int dp[2][510][510];
string a,b;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>m;
cin>>a>>b;a='.'+a,b='.'+b;
dp[0][0][0]=1;
int cur=0;
for(int i=0;i<=n;i++,cur^=1)
for(int j=0;j<=m;j++)
for(int k=0;k<=n;k++){
int l=i+j-k;
int &x=dp[cur][j][k];
if(l<0||l>m)continue;
if(a[i+1]==a[k+1])dp[cur^1][j][k+1]=(dp[cur^1][j][k+1]+x)%mod;
if(a[i+1]==b[l+1])dp[cur^1][j][k]=(dp[cur^1][j][k]+x)%mod;
if(b[j+1]==a[k+1])dp[cur][j+1][k+1]=(dp[cur][j+1][k+1]+x)%mod;
if(b[j+1]==b[l+1])dp[cur][j+1][k]=(dp[cur][j+1][k]+x)%mod;
x=0;
}
cout<<dp[cur][m][n];
return 0;
}