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

    歡迎訪問 生活随笔!

    生活随笔

    當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

    编程问答

    TJOI2018Party

    發布時間:2023/12/1 编程问答 37 豆豆
    生活随笔 收集整理的這篇文章主要介紹了 TJOI2018Party 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

    題目描述

    小豆參加了\(NOI\)的游園會,會場上每完成一個項目就會獲得一個獎章,獎章 只會是\(N\), \(O\), \(I\)的字樣。在會場上他收集到了\(K\)個獎章組成的串。

    兌獎規則是獎章串和兌獎串的最長公共子序列長度為小豆最后獎勵的等級。

    現在已知兌獎串長度為\(N\),并且在兌獎串上不會出現連續三個獎章為\(NOI\),即獎章中不會出現子串\(NOI\)

    現在小豆想知道各個獎勵等級會對應多少個不同的合法兌獎串。

    題解

    我們可以先考忽略那些奇奇怪怪的限制條件,直接考慮如何統計序列數。

    我們先考慮\(LCS\)的dp方法。
    \[ dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+(s[i]==t[j])) \]
    我們如果把第二維單獨拿出來考慮,我們可以發現第二維是一個單調不降的數列而且前后兩項的差是小于等于1的。

    因為第二維的長度非常小,所以我們可以把第二維差分之后狀壓起來作為我們的狀態。

    而且有一個好處,我們知道了這個狀態,就能發當前\(dp\)值還原出來,假設我們知道了下一個字符時什么,我們就可以知道轉移后的狀態是什么了。

    所以我們預處理\(g[i][j]\)表示當前狀態為\(i\),新加入字符為\(j\),能夠轉移的狀態。

    然后我們再設\(dp[i][j][k]\)表示做到第\(i\)為,當前狀態為\(j\),匹配到k個字符(這個是判斷那個特殊限制用的),隨便轉移一下就好了。

    代碼

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int mod=1e9+7; int tran[200],g[3][1<<16],dp[2][1<<16][3],n,k,nw[20],a[20],ma,ans[20]; char s[20]; inline int rd(){int x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x; } inline void MOD(int &x){x=x>=mod?x-mod:x;} int main(){n=rd();k=rd();tran['N']=0;tran['O']=1;tran['I']=2;scanf("%s",s+1);for(int i=1;i<=k;++i)a[i]=tran[(int)s[i]];ma=(1<<k+1);for(int o=0;o<3;++o){for(int i=0;i<ma;++i){for(int j=0;j<=k;++j){nw[j]=(i&(1<<j))!=0;if(j)nw[j]+=nw[j-1]; }for(int j=k;j>=1;--j){nw[j]=max(nw[j],nw[j-1]);if(a[j]==o)nw[j]=max(nw[j],nw[j-1]+1);}for(int j=1;j<=k;++j)nw[j]=max(nw[j],nw[j-1]);int s=0;for(int j=k;j>=1;--j)nw[j]=nw[j]-nw[j-1];for(int j=0;j<=k;++j)s|=(1<<j)*nw[j];g[o][i]=s;}}int now=1,pre=0;dp[now][0][0]=1;for(int i=0;i<n;++i){swap(now,pre);memset(dp[now],0,sizeof(dp[now]));for(int j=0;j<ma;++j)for(int l=0;l<3;++l)if(dp[pre][j][l])for(int p=0;p<3;++p){int no=(p==l)?l+1:(p==0); if(no==3)continue;MOD(dp[now][g[p][j]][no]+=dp[pre][j][l]);}}for(int i=0;i<ma;++i){for(int j=0;j<=k;++j){nw[j]=(i&(1<<j))!=0;if(j)nw[j]+=nw[j-1];} MOD(ans[nw[k]]+=(1ll*dp[now][i][0]+dp[now][i][1]+dp[now][i][2])%mod);} for(int i=0;i<=k;++i)printf("%d\n",ans[i]);return 0; }

    轉載于:https://www.cnblogs.com/ZH-comld/p/10554475.html

    總結

    以上是生活随笔為你收集整理的TJOI2018Party的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。