zoukankan      html  css  js  c++  java
  • [BZOJ]1566: [NOI2009]管道取珠

    Time Limit: 20 Sec  Memory Limit: 650 MB

    Description

    Input

      第一行包含两个整数n, m,分别表示上下两个管道中球的数目。 第二行为一个AB字符串,长度为n,表示上管道中从左到右球的类型。其中A表示浅色球,B表示深色球。 第三行为一个AB字符串,长度为m,表示下管道中的情形。

    Output

      仅包含一行,即为 Sigma(Ai^2) i从1到k 除以1024523的余数。

    Sample Input

      2 1
      AB
      B

    Sample Output

      5

    HINT

      样例即为文中(图3)。共有两种不同的输出序列形式,序列BAB有1种产生方式,而序列BBA有2种产生方式,因此答案为5。
      【大致数据规模】
      约30%的数据满足 n, m ≤ 12;
      约100%的数据满足n, m ≤ 500。

    Solution

      相同方案的平方和等同于分别选出两个序列,它们相同的方案数(实在是妙……)。然后不难用f[i][j][k]表示两个序列各选了i个,第一个在第一行选j个,第二个在第一行选k个,两个序列相同的方案数,可以轻松DP求出答案。

    Code

    #include<cstdio>
    #include<cstring>
    #define MN 500
    #define MOD 1024523
    char a[MN+5],b[MN+5];
    int f[2][MN+5][MN+5];
    inline void rw(int&a,int b){a+=b;if(a>=MOD)a-=MOD;}
    int main()
    {
        int n,m,i,j,k;
        scanf("%d%d%s%s",&n,&m,a+1,b+1);
        f[0][0][0]=1;
        for(i=1;i<=n+m;++i)
        {
            memset(f[i&1],0,sizeof(f[i&1]));
            for(j=0;j<i&&j<=n;++j)for(k=0;k<i&&k<=n;++k)
            {
                if(j<n&&k<n&&a[j+1]==a[k+1])
                    rw(f[i&1][j+1][k+1],f[~i&1][j][k]);
                if(j<n&&i-k<=m&&a[j+1]==b[i-k])
                    rw(f[i&1][j+1][k],f[~i&1][j][k]);
                if(i-j<=m&&k<n&&b[i-j]==a[k+1])
                    rw(f[i&1][j][k+1],f[~i&1][j][k]);
                if(i-j<=m&&i-k<=m&&b[i-j]==b[i-k])
                    rw(f[i&1][j][k],f[~i&1][j][k]);
            }
        }
        printf("%d",f[(n+m)&1][n][n]);
    }
  • 相关阅读:
    hdoj 4006 The kth great number【优先队列】
    hdoj 1509 Windows Message Queue【优先队列】
    nyoj 55 懒省事的小明【优先队列】
    hdoj 1896 Stones【优先队列】
    nyoj 757 期末考试【优先队列+贪心】
    hdoj 2147 kiki's game【博弈】
    hdoj 1873 看病要排队【优先队列】
    hdoj 1789 Doing Homework again
    nyoj 1036 非洲小孩【贪心区间选点】
    转:栈和队列小知识【STL用法】
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ1566.html
Copyright © 2011-2022 走看看