您的位置:首页 > 其它

BZOJ1566 [NOI2009]管道取珠 dp

2018-01-03 21:11 351 查看
有两个栈,每个栈从底向上有一些颜色为A或B的球,现将这些球全部取出,假设能得到k个不同的颜色序列,得到每个序列的方案数为ai.

求∑k
f470
i=1a2i.

这里需要巧妙转化

a2i可以看做两个人每人取一次,取得的序列相同的方案数。

那么设f[i][j][k]为第一个人在上面取i个,下面取j个,第二个人在上面取k个,下面取l=(i+j−k)个的方案数

滚动数组优化第一维,直接n3转移即可

并且卡了一波常数

可能还有更优秀的方法。。

#include<bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=503,mo=1024523;
char s1
,s2
;
int n,m,f[3]

;
inline void add(int &x,int y)
{
x+=y;
if(x>mo)x-=mo;
}
int main()
{
scanf("%d%d%s%s",&n,&m,s1+1,s2+1);
int now=0;
f[now][0][0]=1;
for(int i=0;i<=n;i++)
{
clr(f[now^1],0);
for(int j=0;j<=m;j++)
{
int mk=min(i+j,n);
for(int k=0;k<=mk;k++)
{
int l=i+j-k,v=f[now][j][k];
if(s1[i+1]==s1[k+1])add(f[now^1][j][k+1],v);
if(s1[i+1]==s2[l+1])add(f[now^1][j][k],v);
if(s2[j+1]==s1[k+1])add(f[now][j+1][k+1],v);
if(s2[j+1]==s2[l+1])add(f[now][j+1][k],v);
}
}
now^=1;
}
printf("%d",f[now][m]
);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: