BZOJ 3864 Hero meet devil DP套DP
题目大意:给定一个长度为
考虑
我们发现每一行之和上一行的状态有关
那么在这个问题中,我们令
因为每一行相邻两数最多差
预处理全部转移后直接DP,时间复杂度
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MOD 1000000007
using namespace std;
const char letters[]={'A','C','G','T'};
int n,m;
char s[20];
int trans[1<<15][4],cnt[1<<15],f[2][1<<15];
void Pretreatment()
{
int i,j,k;
for(i=0;i<1<<n;i++)
{
static int f[20],g[20];
for(j=1;j<=n;j++)
f[j]=f[j-1]+(i&(1<<j-1)?1:0);
cnt[i]=f[n];
for(k=0;k<4;k++)
{
for(j=1;j<=n;j++)
{
g[j]=max(g[j-1],f[j]);
if(letters[k]==s[j])
g[j]=max(g[j],f[j-1]+1);
}
trans[i][k]=0;
for(j=1;j<=n;j++)
if(g[j]-g[j-1])
trans[i][k]|=1<<j-1;
}
}
}
int main()
{
int T,i,j,k;
for(cin>>T;T;T--)
{
scanf("%s%d",s+1,&m);
n=strlen(s+1);
Pretreatment();
memset(f,0,sizeof f);
f[0][0]=1;
for(i=1;i<=m;i++)
{
memset(f[i&1],0,sizeof(f[0][0])<<15);
for(j=0;j<1<<n;j++)
for(k=0;k<4;k++)
(f[i&1][trans[j][k]]+=f[~i&1][j])%=MOD;
}
static int ans[20];
memset(ans,0,sizeof ans);
for(i=0;i<1<<n;i++)
(ans[cnt[i]]+=f[m&1][i])%=MOD;
for(i=0;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}