BZOJ3864 & HDU4899:Hero meet devil——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3864
http://acm.hdu.edu.cn/showproblem.php?pid=4899
给你字符集为{A,T,G,C}的字符串,问有多少长度为m的字符串,满足其最长公共子序列长度为0,1……|S|。
太神啦,看巨佬博客吧:https://www.cnblogs.com/RabbitHu/p/BZOJ3864.html
#include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int p=1e9+7; const int N=15; const int M=1010; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int s[N+4]; int m,n,ans[N+4],f[2][1<<N],last[1<<N],trans[1<<N][4]; inline int readstring(){ int cnt=0;char ch=0; while(ch<'A'||ch>'Z')ch=getchar(); while(ch>='A'&&ch<='Z'){ if(ch=='A')s[++cnt]=0;if(ch=='T')s[++cnt]=1; if(ch=='G')s[++cnt]=2;if(ch=='C')s[++cnt]=3; ch=getchar(); } return cnt; } void init(){ static int d[N+4],g[N+4]; for(int i=0;i< 1<<n;i++){ if(i)last[i]=last[i^(i&-i)]+1; for(int j=0;j<n;j++)d[j+1]=d[j]+(bool)(i&(1<<j)); for(int k=0;k<4;k++){ for(int j=1;j<=n;j++){ g[j]=max(g[j-1],d[j]); if(s[j]==k)g[j]=max(g[j],d[j-1]+1); } trans[i][k]=0; for(int j=0;j<n;j++) if(g[j+1]-g[j])trans[i][k]|=1<<j; } } memset(ans,0,sizeof(ans)); memset(f,0,sizeof(f)); } int main(){ int T=read(); while(T--){ n=readstring();m=read(); init(); f[0][0]=1;int now=1; for(int i=1;i<=m;i++){ memset(f[now],0,sizeof(f[now])); for(int j=0;j< 1<<n;j++){ for(int k=0;k<4;k++){ (f[now][trans[j][k]]+=f[now^1][j])%=p; } } now^=1; } for(int i=0;i< 1<<n;i++) (ans[last[i]]+=f[now^1][i])%=p; for(int i=0;i<=n;i++)printf("%d\n",ans[i]); } return 0; }