zoukankan      html  css  js  c++  java
  • 洛谷1758 BZOJ1566 管道取珠题解

    题目链接

    一道人类智慧的dp题

    首先我们可以将∑ai^2转化为求取两次,两次一样的方案数

    然后用f[i][j][k][l]表示第一个人在第一个串中取到i第二个串中取到j

    第二个人在一个串中取到k第二个串中取到l的方案数

    显然i+j=k+l,所以第四维可以省掉

    推出方程后,可以看出f[i][j][k][l]只与f[i]与f[i-1]有关,所以可以用滚动数组优化

    // luogu-judger-enable-o2
    # include<iostream>
    # include<cmath>
    # include<algorithm>
    # include<cstdio>
    const int rqy = 1024523;
    const int mn = 505;
    char a[mn],b[mn];
    int f[5][mn][mn];
    inline void cal(int &a,int &b)
    {
        a=a+b;
        if(a>=rqy)
            a-=rqy;
    }
    int n,m;
    int main()
    {
        scanf("%d%d",&n,&m);
        scanf("%s",a+1);
        scanf("%s",b+1);
        int cur=0;
        f[0][0][0]=1;
        for(int i=0;i<=n;i++,cur^=1)
            for(int j=0;j<=m;j++)
              for(int k=0;k<=n;k++)
        {
           if(i+j-k>m || i+j-k<0) continue;
           if(a[i+1]==a[k+1])
            cal(f[cur^1][j][k+1],f[cur][j][k]);
           if(a[i+1]==b[i+j-k+1])
            cal(f[cur^1][j][k],f[cur][j][k]);
           if(b[j+1]==b[i+j-k+1])
            cal(f[cur][j+1][k],f[cur][j][k]);
           if(b[j+1]==a[k+1])
            cal(f[cur][j+1][k+1],f[cur][j][k]);
           f[cur][j][k]=0;
        }
        printf("%d",f[cur][m][n]);
        return 0;
    }
  • 相关阅读:
    验证码
    九九乘法表
    P121 6.7 第一题和第二题
    二分搜索法(转载自vanezkw)
    用for循环打印菱形
    用while循环语句计算1!+2!+……20!之和
    数的阶乘之和
    9.29
    doGet与doPost的区别
    JavaScript习题
  • 原文地址:https://www.cnblogs.com/logeadd/p/8780132.html
Copyright © 2011-2022 走看看