bzoj 3864: Hero meet devil

Posted Nico&11101001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3864: Hero meet devil相关的知识,希望对你有一定的参考价值。

bzoj3864次元联通们

第一次写dp of dp (:з」∠) 不能再颓废啦
考虑最长匹配序列匹配书转移
由于dp[i][j]的转移可由上一行dp[i-1][j-1],dp[i-1][j],dp[i][j-1]得来
把dp[i]差分,得到一个01串
就可以用rans[s][ch]表示在状态s的dp数组后面接字符ch可以转移到的状态
枚举该转移就好了QAQ

/**************************************************************
    Problem: 3864
    Language: C++
    Result: Accepted
    Time:4208 ms
    Memory:2356 kb
****************************************************************/
//f[i]为之前前i项的LCS,g[i]为添加字母之后的
//g数组的差值就是下一次匹配转移到的状态
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::memset;
const int mod= 1000000007;
inline int read() {
    int x=0,f=1;
    char c=getchar() ;
    while(c<'0'||c>'9') {
         if(c=='-')f=-1;
         c=getchar();
    }
    while(c<='9'&&c>='0') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}const int maxn = 16;
int cnt,m,n;
char a[40];
int tans[1<<maxn][4];
int ans[2][1<<maxn],f[maxn],g[maxn];
int is[maxn];
int s[maxn];
void network(int maxx) {
    int now=1;
    memset(ans,0,sizeof ans);
    ans[0][0]=1;
    for(int i=1;i<=m;++i,now=i&1) {
        for(int j=0;j<4;++j) 
            for(int e=0;e<maxx;++e)
                ans[now][tans[e][j]]=(ans[now][tans[e][j]]+ans[now^1][e])%mod;
        memset(ans[now^1],0,sizeof ans[now^1]);
        //now=i&1;
    }
    now^=1;
    memset(is,0,sizeof is);
    for(int i=0;i<maxx;++i) is[__builtin_popcount(i)]=(is[__builtin_popcount(i)]+ans[now][i])%mod;
    for(int i=0;i<=n;++i)printf("%d\n",is[i]);
}
void solve(int m,int n) {
    int maxx=1<<n;
    for(int i=0;i<maxx;++i) {
        f[0]=i&1;
        for(int j=1;j<n;++j) f[j]=((i>>j)&1)+f[j-1];
        for(int j=0;j<4;++j) {
            memset(g,0,sizeof g);
            for(int e=0;e<n;++e) {
                if(s[e]==j) g[e] = f[e-1]+1;//最后一位与原来匹配
                else g[e]=std::max(g[e-1],f[e]);
            }
            int tmp = 0;
            for(int e=0;e<n;++e)
                if(g[e]==g[e-1]+1)
                    tmp|=1<<e;
            tans[i][j]=tmp;
        }
    }
    network(maxx);
}
int main() {
    cnt=read();
    for(int i=1;i<=cnt;++i) {
        scanf("%s",a);
        m=read();n=strlen(a);
        for(int i=0;i<n;++i) 
            if(a[i]=='A') s[i]=0;
            else if(a[i]=='T') s[i]=1;
            else if(a[i]=='C') s[i]=2;
            else if(a[i]=='G') s[i]=3;
        solve(m,n);
    }
    return 0;
}

以上是关于bzoj 3864: Hero meet devil的主要内容,如果未能解决你的问题,请参考以下文章

bzoj千题计划241:bzoj3864: Hero meet devil

bzoj 3864: Hero meet devil(dp套dp)

BZOJ 1191 超级英雄 Hero 题解

bzoj 1191: [HNOI2006]超级英雄Hero

bzoj 1191 超级英雄Hero

BZOJ-1787Meet紧急集合 倍增LCA