zoukankan      html  css  js  c++  java
  • bzoj 3864: Hero meet devil(dp套dp)

    题面

    给你一个只由(AGCT)组成的字符串(S (|S| ≤ 15)),对于每个(0 ≤ .. ≤ |S|),问
    有多少个只由(AGCT)组成的长度为(m(1 ≤ m ≤ 1000))的字符串(T),使得(LCS(T,S)=i)

    题解

    老早就听说这个叫做(dp of dp)的神仙了……然而一直没学……

    我们先考虑(LCS)是怎么转移的,设(LCS(i,j))表示第一个串到(i),第二个串到(j)为止的最长公共子序列,那么转移为

    [LCS(i,j)=max egin{cases} LCS(i-1,j-1)+1 &S[i]=T[j]\ LCS(i,j-1)\ LCS(i-1,j) end{cases} ]

    然后我们发现(LCS(i,j))的值和(LCS(i,j-1))的值相差最多不会超过(1)

    那么我们把数组的第二维差分一下,再状压成一个二进制序列,然后我们就可以预处理出(to[s][k])表示当前(LCS)状态为(s),加的下一个字符为(k),可以到达的(LCS)状态是什么

    然后设(f[i][s])表示当前在第(i)个位置,此时(LCS)状态为(s)的方案数

    那么转移方程就是

    [f[i][to[s][k]]+=f[i-1][s](k=A,T,G,C) ]

    边界为(f[0][0]=1)

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    const char T[15]={"ATGC"};const int N=(1<<15)+5,P=1e9+7;
    inline void Add(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    char S[19];int to[N][4],sz[N],f[2][N],ans[1005];
    int n,m,lim,t;
    void init(){
    	static int d[19],g[19];
    	fp(s,0,lim-1){
    		sz[s]=sz[s>>1]+(s&1);
    		fp(j,0,n-1)d[j+1]=d[j]+(s>>j&1);
    		fp(k,0,3){
    			fp(j,1,n){
    				g[j]=max(g[j-1],d[j]);
    				T[k]==S[j]?cmax(g[j],d[j-1]+1):0;
    			}
    			to[s][k]=0;
    			fp(j,0,n-1)g[j+1]-g[j]?(to[s][k]|=(1<<j)):0;
    		}
    	}
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	int cas;scanf("%d",&cas);
    	while(cas--){
    		scanf("%s%d",S+1,&m),n=strlen(S+1),lim=(1<<n);
    		init(),memset(ans,0,4*(n+1)),memset(f,0,sizeof(f));
    		f[0][0]=1,t=0;
    		for(R int i=1;i<=m;++i,t^=1){
    			memset(f[t^1],0,4*lim);
    			fp(s,0,lim-1)fp(k,0,3)Add(f[t^1][to[s][k]],f[t][s]);
    		}
    		fp(s,0,lim-1)Add(ans[sz[s]],f[t][s]);
    		fp(i,0,n)printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    android UI 适配小节
    Android中的倒计时实现
    几种适配器&观察者&ListView之间的那点事
    Service stopSelf(int statId)和onStartcommand(Intent intent,int flags,int startId)
    java 虚函数
    java 重载和多态的区别
    小程序体验版路径以及参数携带
    微信小程序--上传图片公用组件
    微信小程序页面返回
    js兼容安卓和IOS的复制文本到剪切板
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10534010.html
Copyright © 2011-2022 走看看