• BZOJ3864 Hero meet devil


    Description

    给出一个字符串S,这个字符串只由,ACGT四个字母组成。对于每个1一|S|中的每一个i.求出满足以下条件的字符串T的个数:

    • 长度为m 
    • 只由ACGT组成
    • lcs为i 

    Solution

    第一步考虑已知两个串,计算两串之间的lcs,i表示A串指针,j表示B串指针

    $$f[i][j]=max(f[i-1][j],f[i][j-1])$$

    $$if(s[i]==t[j]) f[i][j]=max(f[i-1][j-1]+1)$$

    由于s串比较短,把f数组用差分压缩成二进制状态 第二步是外层DP,$dp[i][j]$表示,已经生成了i位的字符串,此时lcs为j的字符串个数;$tr[j][k]$表示j状态下增加字符k得到的状态

    $$dp[i+1][tr[j][k]]+=dp[i][j]$$

    DP套DP求解

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int T,n,m,a[20],tran[100000][4],f[2][20],dp[1005][40000],ans[20];
    const int mod=1000000007;
    char s[20];
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    int change(char x)
    {
        if(x=='A')
            return 1;
        if(x=='C')
            return 2;
        if(x=='G')
            return 3;
        return 4;
    }
    int trans(int v,int c)
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<n;i++)
            f[0][i+1]=f[0][i]+((v>>i)&1);
        for(int i=1;i<=n;i++)
        {
            f[1][i]=max(f[0][i],f[1][i-1]);
            if(a[i]==c)
                f[1][i]=max(f[1][i],f[0][i-1]+1);
        }
        int ret=0;
        for(int i=0;i<n;i++)
            if(f[1][i+1]-f[1][i])
                ret|=(1<<i);
        return ret;
    }
    int cnt(int x)
    {
        int ret=0;
        while(x)
        {
            if(x&1)
                ret++;
            x>>=1;
        }
        return ret;
    }
    int main()
    {
        T=read();
        for(;T;T--)
        {
            memset(dp,0,sizeof(dp));
            memset(ans,0,sizeof(ans));
            scanf("%s",s+1);
            m=read();
            n=strlen(s+1);
            for(int i=1;i<=n;i++)
                a[i]=change(s[i]);    
            for(int i=0;i<(1<<n);i++)
                for(int j=1;j<=4;j++)
                    tran[i][j]=trans(i,j);
            dp[0][0]=1;
            for(int i=1;i<=m;i++)
                for(int j=0;j<(1<<n);j++)
                    for(int k=1;k<=4;k++)
                    {
                        int temp=tran[j][k];
                        (dp[i][temp]+=dp[i-1][j])%=mod;
                    }
            for(int i=0;i<(1<<n);i++)
                (ans[cnt(i)]+=dp[m][i])%=mod;
            for(int i=0;i<=n;i++)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
    Hero meet devil
  • 相关阅读:
    w3c盒子模型与ie盒子模型
    前端入门
    连接数据库好用工具
    前端开发工具
    刚发现的取色工具
    使用val()另一个妙用------选中select/checkbox/radio的值
    z-index的妙用
    react生命周期函数
    react中虚拟dom的diff算法
    React中的虚拟DOM
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13394092.html
Copyright © 2020-2023  润新知