bzoj 1566 NOI 2009 管道取珠 DP 解题报告
2017-07-05 16:49
471 查看
Description
Input
第一行包含两个整数n, m,分别表示上下两个管道中球的数目。 第二行为一个AB字符串,长度为n,表示上管道中从左到右球的类型。其中A表示浅色球,B表示深色球。 第三行为一个AB字符串,长度为m,表示下管道中的情形。Output
包含一行,即为 Sigma(Ai^2) i从1到k 除以1024523的余数。Sample Input
2 1AB
B
Sample Output
5HINT
样例即为文中(图3)。共有两种不同的输出序列形式,序列BAB有1种产生方式,而序列BBA有2种产生方式,因此答案为5。【大致数据规模】
约30%的数据满足 n, m ≤ 12;约100%的数据满足n, m ≤ 500。
【解题报告】
两次取的序列一样,可以看成两个人分别玩一次,然后两个人得到的序列一样.那这个题就变成了两个人各玩一次,求第一个人每次得到的序列在第二个人得到的序列中出现的次数和.
设f[i][j][k]表示第i个珠子,第一个人在上方取了j个,第二个人在上方取了k个的答案.
这个直接dp即可.
代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int mod=1024523 const int N=500+10; int n,m,dp[2] ,a ,b ,t; char s1 ,s2 ; int main() { scanf("%d%d",&n,&m); scanf("%s%s",s1,s2); for (int i=0;i<n;++i) a[n-i]=s1[i]-'A'; for (int i=0;i<m;++i) b[m-i]=s2[i]-'A'; dp[0][0][0]=1; for (int i=0;i<n+m;++i) { t=i%2; for (int j=0;j<=n&&j<=i;++j) for (int k=0;k<=n&&j<=i;++k) if (dp[t][j][k]) { if (a[j+1]==b[i-k+1]) (dp[!t][j+1][k]+=dp[t][j][k])%=mod; if (b[i-j+1]==a[k+1]) (dp[!t][j][k+1]+=dp[t][j][k])%=mod; if (b[i-j+1]==b[i-k+1]) (dp[!t][j][k]+=dp[t][j][k])%=mod; if (a[j+1]==a[k+1]) (dp[!t][j+1][k+1]+=dp[t][j][k])%=mod; dp[t][j][k]=0; } } printf("%d\n",dp[(n+m)%2] ); return 0; }
相关文章推荐
- bzoj 1566: [NOI2009]管道取珠 (DP)
- [BZOJ1566][NOI2009]管道取珠(DP)
- BZOJ1566 [NOI2009]管道取珠 【dp】
- BZOJ1566 [NOI2009]管道取珠 dp
- [平方的拆分 DP] BZOJ 1566 [NOI2009]管道取珠
- 【BZOJ 1566】 1566: [NOI2009]管道取珠 (DP)
- BZOJ 1566: [NOI2009]管道取珠 另类DP
- bzoj 1566: [NOI2009]管道取珠【dp】
- 【bzoj1566】【NOI2009】【管道取珠】【dp】
- [BZOJ 1566][NOI2009]管道取珠(DP)
- bzoj1566 [NOI2009]管道取珠
- bzoj1566: [NOI2009]管道取珠
- [BZOJ1026][SCOI2009]windy数 解题报告|数位dp
- BZOJ1566 [NOI2009]管道取珠
- bzoj1566【Noi2009】管道取珠
- BZOJ 1566 DP 解题报告
- bzoj1566 [NOI2009]管道取珠
- bzoj1566 [NOI2009]管道取珠
- [BZOJ 1056][NOI 2009]管道取珠(DP)
- [BZOJ1566][NOI2009]管道取珠