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;
    }
  • 相关阅读:
    [bzoj1251]序列终结者
    Codeforces #Round 406(Div.2)
    [3.23校内训练赛]
    [APIO2009]
    [APIO2016]
    [bzoj1901]动态区间k大
    [9018/1904]火星商店
    [bzoj3673/3674可持久化并查集加强版]
    [bzoj1297][SCOI2009]迷路
    [bzoj1218][HNOI2003]激光炸弹
  • 原文地址:https://www.cnblogs.com/logeadd/p/8780132.html
Copyright © 2011-2022 走看看