bzoj1566 [NOI2009]管道取珠
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1566 [NOI2009]管道取珠相关的知识,希望对你有一定的参考价值。
Description
Input
第一行包含两个整数n, m,分别表示上下两个管道中球的数目。 第二行为一个AB字符串,长度为n,表示上管道中从左到右球的类型。其中A表示浅色球,B表示深色球。 第三行为一个AB字符串,长度为m,表示下管道中的情形。
Output
仅包含一行,即为 Sigma(Ai^2) i从1到k 除以1024523的余数。
Sample Input
2 1
AB
B
AB
B
Sample Output
5
HINT
样例即为文中(图3)。共有两种不同的输出序列形式,序列BAB有1种产生方式,而序列BBA有2种产生方式,因此答案为5。
【大致数据规模】
约30%的数据满足 n, m ≤ 12;
约100%的数据满足n, m ≤ 500。
正解:$dp$。
思路比较巧妙。注意到$a_{i}$平方以后不好处理,那么我们可以下意识地想到,其实这就是$4$个管道输出序列相同的一种情况。两个管道相同的有$a_{i}$种方案,那么$4$个管道方案组合,自然也就有$a_{i}^{2}$种方案了。
接下来的事就很简单了,设$f[i][j][k][l]$表示$4$个管道分别丢了第$i$个,第$j$个,第$k$个,第$l$个珠子的相同序列方案数。因为我们要求两个序列要相同,所以很显然,$i+j=k+l$,于是我们可以去掉$l$这一维状态。然后我们判断$4$个珠子两两相等的情况转移就行了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define rhl (1024523) 14 #define il inline 15 #define RG register 16 #define ll long long 17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 18 19 using namespace std; 20 21 int f[510][510][510],n,m; 22 char a[510],b[510]; 23 24 il int gi(){ 25 RG int x=0,q=1; RG char ch=getchar(); 26 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 27 if (ch==‘-‘) q=-1,ch=getchar(); 28 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 29 return q*x; 30 } 31 32 il void work(){ 33 n=gi(),m=gi(),scanf("%s",a+1),scanf("%s",b+1); 34 reverse(a+1,a+n+1),reverse(b+1,b+m+1),f[0][0][0]=1; 35 for (RG int i=0;i<=n;++i) 36 for (RG int j=0;j<=m;++j) 37 for (RG int k=0;k<=n && k<=i+j;++k){ 38 if (a[i]==a[k] && i && k){ 39 f[i][j][k]+=f[i-1][j][k-1]; 40 if (f[i][j][k]>=rhl) f[i][j][k]-=rhl; 41 } 42 if (a[i]==b[i+j-k] && i){ 43 f[i][j][k]+=f[i-1][j][k]; 44 if (f[i][j][k]>=rhl) f[i][j][k]-=rhl; 45 } 46 if (b[j]==a[k] && j && k){ 47 f[i][j][k]+=f[i][j-1][k-1]; 48 if (f[i][j][k]>=rhl) f[i][j][k]-=rhl; 49 } 50 if (b[j]==b[i+j-k] && j){ 51 f[i][j][k]+=f[i][j-1][k]; 52 if (f[i][j][k]>=rhl) f[i][j][k]-=rhl; 53 } 54 } 55 printf("%d\n",f[n][m][n]); return; 56 } 57 58 int main(){ 59 File("pipe"); 60 work(); 61 return 0; 62 }
以上是关于bzoj1566 [NOI2009]管道取珠的主要内容,如果未能解决你的问题,请参考以下文章