把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

BZOJ #3864. Hero meet devil

题面传送门
树能套,dp居然也能套/jk
首先我们先来思考LCS一般是怎么做的。
显然是设\(f_{i,j}\)为第一个串匹配到\(i\),第二个匹配到\(j\),答案为多少。
我们考虑直接将这个东西压到状态里面。
具体的,设\(g_{i,S}\)表示不定串匹配到第\(i\)个时,\(dp_{i}\)的状态是\(S\),转移是平凡的,但是状态数有\(m|S|^{|S|}\)个无法接受。
显然LCS具有单调性,\(dp_{i,j}\leq dp_{i,j+1}\leq dp_{i,j}+1\),因此可以差分后存状态,状态数就变成\(O(m2^{|S|})\),总时间复杂度\(O(Tm2^{|S|}|S|)\)
但是275307894a的常数非常大以至于他根本没法在5s内跑完这个东西,于是他就预处理了状态转移做到\(O(Tm2^{|S|})\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (15+5)
#define M (1000+5)
#define K ((1<<15)+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int T,n,m,k,x,y,z,Ne,La,A[N],B[N],P1[K],P2[K],P3[K],P4[K];ll dp[2][K],Ans[N];char s[N];
I void Solve(){
	int i,j,h;scanf("%s",s+1);n=strlen(s+1);scanf("%d",&m);Me(dp,0);Ne=0;La=1;dp[0][0]=1;
	for(i=0;i<(1<<n);i++){
		for(j=1;j<=n;j++) A[j]=A[j-1]+(i>>(j-1)&1);Mc(B,A);
		P1[i]=0;Mc(A,B);for(j=n;j;j--) s[j]=='A'&&(A[j]=max(A[j],A[j-1]+1));for(j=1;j<=n;j++) A[j]=max(A[j],A[j-1]),P1[i]|=(A[j]-A[j-1]<<j-1);
		P2[i]=0;Mc(A,B);for(j=n;j;j--) s[j]=='T'&&(A[j]=max(A[j],A[j-1]+1));for(j=1;j<=n;j++) A[j]=max(A[j],A[j-1]),P2[i]|=(A[j]-A[j-1]<<j-1);
		P3[i]=0;Mc(A,B);for(j=n;j;j--) s[j]=='G'&&(A[j]=max(A[j],A[j-1]+1));for(j=1;j<=n;j++) A[j]=max(A[j],A[j-1]),P3[i]|=(A[j]-A[j-1]<<j-1);
		P4[i]=0;Mc(A,B);for(j=n;j;j--) s[j]=='C'&&(A[j]=max(A[j],A[j-1]+1));for(j=1;j<=n;j++) A[j]=max(A[j],A[j-1]),P4[i]|=(A[j]-A[j-1]<<j-1);
	}
	for(i=1;i<=m;i++){Ne^=1;La^=1;Me(dp[Ne],0);
		for(j=0;j<(1<<n);j++){if(!dp[La][j]) continue;dp[La][j]%=mod;dp[Ne][P1[j]]+=dp[La][j];dp[Ne][P2[j]]+=dp[La][j];dp[Ne][P3[j]]+=dp[La][j];dp[Ne][P4[j]]+=dp[La][j];}
	}
	Me(Ans,0);for(i=0;i<(1<<n);i++) {x=i;y=0;while(x) y++,x-=x&-x;Ans[y]+=dp[Ne][i];}for(i=0;i<=n;i++) printf("%lld\n",Ans[i]%mod);
}
int main(){
	freopen("1.in","r",stdin);
	scanf("%d",&T);while(T--) Solve();
}
posted @ 2022-06-30 15:04  275307894a  阅读(41)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end