日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時間:2023/12/10 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj千题计划241:bzoj3864: Hero meet devil 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://www.lydsy.com/JudgeOnline/problem.php?id=3864

?

題意:

給你一個DNA序列,求有多少個長度為m的DNA序列和給定序列的LCS為0,1,2....

?

求LCS方式:f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]*(s[i]==t[j]))

固定了i,相鄰的j的f[i][j]值最多相差1

dp[i][j] 表示長度為i的DNA序列,將“f[ |S| ][j+1]是否比f[ |S| ][j] 大1” 這個狀態(tài)壓縮為j的方案數(shù)

若我們知道?狀態(tài)j加上一個字母k可以到狀態(tài)nxt[j][k]

那么dp[i+1][nxt[j][k]]+=dp[i][j]

?

關(guān)鍵是如何求得nxt[j][k]

再一次DP

枚舉所有的狀態(tài)i

令f[j] 表示加上字母k之前的LCS長度,g[j]表示加上字母k之后的LCS長度

g[j]=max(g[j-1],f[j])

如果加上的字母k和原序列第j個字母匹配 g[i]=max(g[j],f[j-1]+1)

g求完后,項鄰的兩個g要么相等,要么相差1

再把這個狀態(tài)壓縮起來即可

?

#include<cstdio> #include<cstring> #include<algorithm>using namespace std;const int mod=1e9+7;int m;char ss[16]; int L,S; int s[16];int ch[26];int f[16],g[16]; int nxt[1<<15][4];int dp[2][1<<15]; int ans[16];void pre() {int len; int c[16];for(int i=0;i<S;++i){memset(f,0,sizeof(f));for(int j=1;j<=L;++j) f[j]=f[j-1]+(i>>j-1&1);for(int k=0;k<4;++k){for(int j=1;j<=L;++j){g[j]=max(g[j-1],f[j]);if(s[j]==k) g[j]=max(g[j],f[j-1]+1);}nxt[i][k]=0;for(int j=0;j<L;++j)if(g[j+1]-g[j]) nxt[i][k]+=1<<j;}} }int count(int x) {int sum=0;while(x){sum+=x&1;x>>=1;}return sum; }void DP() {memset(dp,0,sizeof(dp));int now=1,last=0;dp[0][0]=1;for(int i=1;i<=m;++i){memset(dp[now],0,sizeof(dp[now]));for(int j=0;j<S;++j)for(int k=0;k<4;++k){dp[now][nxt[j][k]]+=dp[last][j];dp[now][nxt[j][k]]-=dp[now][nxt[j][k]]>=mod ? mod : 0;}swap(now,last);}memset(ans,0,sizeof(ans));int t;for(int i=0;i<S;++i) {t=count(i);ans[t]+=dp[last][i];ans[t]-=ans[t]>=mod ? mod : 0;}for(int i=0;i<=L;++i) printf("%d\n",ans[i]); }int main() {ch['A'-'A']=0;ch['C'-'A']=1;ch['G'-'A']=2;ch['T'-'A']=3;int T;scanf("%d",&T);while(T--){scanf("%s",ss+1);scanf("%d",&m);L=strlen(ss+1);S=1<<L;for(int i=1;i<=L;++i) s[i]=ch[ss[i]-'A'];pre();DP();}return 0; }

?

轉(zhuǎn)載于:https://www.cnblogs.com/TheRoadToTheGold/p/8454799.html

總結(jié)

以上是生活随笔為你收集整理的bzoj千题计划241:bzoj3864: Hero meet devil的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。