zoukankan      html  css  js  c++  java
  • [bzoj1566][NOI2009]管道取珠

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    n<=500

    神题......

    发现这个平方可以看作两个序列相同的对数  然后就可以表示状态了。

    f[i][j][k]表示两个序列各选了i个,第1个序列在第一行选了j个,第二个序列在第二行选了k个,他们相同的方案数

    转移比较简单,枚举两个序列各填哪一位即可。

    复杂度n^3

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 500
    #define mod 1024523
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    int f[2][505][505],n,m;
    char A[MN+5],B[MN+5];
    inline void R(int&x,int y){x+=y;x>=mod?x-=mod:0;}
    int main()
    {
        n=read();m=read();
        scanf("%s",A+1);scanf("%s",B+1);
        f[0][0][0]=1;
        for(int i=0,now=1,pre=0;i<n+m;++i)
        {
            for(int j=0;j<=min(i,n);++j)
                for(int k=0;k<=min(i,n);++k)
                {
                    int J=i-j,K=i-k;
                    if(j<n&&k<n&&A[j+1]==A[k+1]) R(f[now][j+1][k+1],f[pre][j][k]);
                    if(j<n&&K<m&&A[j+1]==B[K+1]) R(f[now][j+1][k],f[pre][j][k]);
                    if(J<m&&k<n&&B[J+1]==A[k+1]) R(f[now][j][k+1],f[pre][j][k]);
                    if(J<m&&K<m&&B[J+1]==B[K+1]) R(f[now][j][k],f[pre][j][k]); 
                }     
            swap(now,pre);
            memset(f[now],0,sizeof(f[now])); 
        }
        printf("%d
    ",f[(n+m)&1][n][n]);
        return 0;
    }
  • 相关阅读:
    [HAOI2008]糖果传递
    [HAOI2008]木棍分割
    [HAOI2008]硬币购物
    [ZJOI2008]泡泡堂
    [JSOI2007]建筑抢修
    [JSOI2007]麻将
    [Note]prufer
    [BZOJ3275]Number
    [POI2014]RAJ-Rally
    [JSOI2010]快递服务
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1566.html
Copyright © 2011-2022 走看看