zoukankan      html  css  js  c++  java
  • BZOJ.1566.[NOI2009]管道取珠(DP 思路)

    BZOJ
    洛谷


    考虑(a_i^2)有什么意义:两个人分别操作原序列,使得得到的输出序列都为(i)的方案数。(sum a_i^2)就是两人得到的输出序列相同的方案数。
    (f[i][j][k])表示第一个人上管道取到了第(i)个球,下管道取到了第(j)个球,第二个人上管道取到了第(k)个球,的方案数。转移很简单。

    复杂度(O(n^3))


    //2816kb	1072ms
    #include <cstdio>
    #include <algorithm>
    #define mod 1024523
    #define Mod(x) x>=mod&&(x-=mod)
    #define Add(x,v) (x+=v)>=mod&&(x-=mod)
    typedef long long LL;
    const int N=505;
    
    int main()
    {
    	static int f[2][N][N];
    	static char A[N],B[N];
    	int n,m; scanf("%d%d",&n,&m);
    	scanf("%s%s",A+1,B+1);
    	std::reverse(A+1,A+1+n), std::reverse(B+1,B+1+m);
    	A[n+1]='?', B[m+1]='!';
    	int p=0; f[p][0][0]=1;
    	for(int i=0; i<=n; ++i,p^=1)
    		for(int j=0; j<=m; ++j)
    			for(int k=0,v; k<=n; ++k)
    				if((v=f[p][j][k]))
    				{
    					if(A[i+1]==A[k+1]) Add(f[p^1][j][k+1],v);
    					if(A[i+1]==B[i+j-k+1]) Add(f[p^1][j][k],v);
    					if(B[j+1]==A[k+1]) Add(f[p][j+1][k+1],v);//p不变啊(日常制杖)
    					if(B[j+1]==B[i+j-k+1]) Add(f[p][j+1][k],v);
    					if(i+j==n+m) return printf("%d
    ",f[p][m][n]),0;
    					f[p][j][k]=0;
    				}
    	puts("Miaomiaomiao?");
    
    	return 0;
    }
    
  • 相关阅读:
    合并区间
    编程团体赛
    寻找数组的中间位置
    翻转链表2
    链表翻转
    CF1237H. Balanced Reversals
    arc108E
    agc028D
    CF1446D. Frequency Problem
    CF1439D. INOI Final Contests
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10375509.html
Copyright © 2011-2022 走看看