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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[CSA49G][XSY3315] Bunny on Number Line (DP)

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CSA49G][XSY3315] Bunny on Number Line (DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CSA49G
XSY3315
因為判斷兩串是否本質不同只看某幾項是不是好數,與究竟是哪個好數無關,所以考慮轉換一下題意:
給出一個長度為aka_kak?的01串SSS,第a1,a2,...,aka_1,a_2,...,a_ka1?,a2?,...,ak?項為1,其余項為0。
現要用若干個SSS的前綴拼出串TTT,使得TTT中有nnn個1,以1結尾,并且任意兩個1之間0的個數不超過mmm。問所有不同的TTT的長度之和為多少?

SSS如果用01串表示,會很長,發現kkk很小,考慮換一種表示方式:設bi=ai?ai?1b_i=a_i-a_{i-1}bi?=ai??ai?1?。我們把SSS串描述成{b1,b2,b3,...,bk}\{b_1,b_2,b_3,...,b_k\}{b1?,b2?,b3?,...,bk?},表示SSS(b1?1)(b_1-1)(b1??1)個0,1個1,(b2?1)(b_2-1)(b2??1)個0,1個1,…,(bk?1)(b_k-1)(bk??1)個0,1個1 拼接而成。

g(x,i)g(x,i)g(x,i)表示目前有xxx個1,以 (bi?1)(b_i-1)(bi??1)個0+1個1 結尾的01串個數,
f(x,i)f(x,i)f(x,i)表示目前有xxx個1,以 (bi?1)(b_i-1)(bi??1)個0+1個1 結尾的01串長度之和。
可以列出dp式:

g(x,i)={g(x?1,i?1)i>1∑j=1kg(x?1,j)×(m?a[1]+1)i=1g(x,i)=\begin{cases}g(x-1,i-1)\qquad i>1\\\sum_{j=1}^{k}g(x-1,j)\times(m-a[1]+1)\qquad i=1\end{cases}g(x,i)={g(x?1,i?1)i>1j=1k?g(x?1,j)×(m?a[1]+1)i=1?

f(x,i)={f(x?1,i?1)+(a[i]?a[i?1])×g(x?1,i?1)i>1∑j=1kf(x?1,j)×(m?a[1]+1)+g(x?1,j)×(a[1]+m)(m?a[1]+1)2i=1f(x,i)=\begin{cases}f(x-1,i-1)+(a[i]-a[i-1])\times g(x-1,i-1)\qquad i>1\\\sum_{j=1}^{k}f(x-1,j)\times(m-a[1]+1)+g(x-1,j)\times\frac{(a[1]+m)(m-a[1]+1)}{2}\qquad i=1\end{cases}f(x,i)={f(x?1,i?1)+(a[i]?a[i?1])×g(x?1,i?1)i>1j=1k?f(x?1,j)×(m?a[1]+1)+g(x?1,j)×2(a[1]+m)(m?a[1]+1)?i=1?

把式子用矩陣快速冪優化一下,復雜度是O(k3logn)O(k^3logn)O(k3logn)
(ps.因為fff的轉移同時與f,gf,gf,g有關,所以通過矩乘轉移的過程有點特殊,具體可以看代碼。)

然而還有一個小小的問題:
假設a={2,6,7,9,13}a=\{2,6,7,9,13\}a={2,6,7,9,13}
那么S[1?13]=0100011010001S[1-13]=0100011010001S[1?13]=0100011010001S[1?6]=010001S[1-6]=010001S[1?6]=010001S[1?7]=0100011S[1-7]=0100011S[1?7]=0100011
我們發現S[1?7]+S[1?6]=S[1?13]S[1-7]+S[1-6]=S[1-13]S[1?7]+S[1?6]=S[1?13],即若S[1?y]S[1-y]S[1?y]S[1?x]S[1-x]S[1?x]的后綴,則S[1?x]S[1-x]S[1?x]可以由S[1?y]S[1-y]S[1?y],S[1?(x?y)]S[1-(x-y)]S[1?(x?y)]拼成。但仔細看上面的dp式就會發現S[1?7]+S[1?6]S[1-7]+S[1-6]S[1?7]+S[1?6]S[1?13]S[1-13]S[1?13]被算成了兩個串。怎么辦?暴力預處理一下,對于前綴S[1?x]S[1-x]S[1?x],若有前綴S[1?y]S[1-y]S[1?y]同時是S[1?x]S[1-x]S[1?x]的后綴,則前綴S[1?x]S[1-x]S[1?x]不能取。

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; const int K=110; int kk,m,n,a[K],pd[K][K],flag[K],ans; struct Matrix{int n,m,g[K][K],f[K][K];//g:個數 f:長度和 Matrix(int x=0,int y=0){memset(f,0,sizeof(f));memset(g,0,sizeof(g));n=x,m=y;}friend Matrix operator * (Matrix a,Matrix b){Matrix res(a.n,b.m);for(int i=1;i<=a.n;i++){for(int j=1;j<=b.m;j++){__int128 g=0,f=0;for(int k=1;k<=a.m;k++){g+=1ll*a.g[i][k]*b.g[k][j];f+=1ll*a.f[i][k]*b.g[k][j]+1ll*a.g[i][k]*b.f[k][j];}res.g[i][j]=int(g%mod);res.f[i][j]=int(f%mod);}}return res;} }; int Sum(ll x,ll y){return (x+y)*(y-x+1)/2%mod; } int main(){scanf("%d%d%d",&kk,&m,&n);for(int i=1;i<=kk;i++) scanf("%d",&a[i]);sort(a+1,a+kk+1);pd[1][1]=1;for(int i=2;i<=kk;i++){int fl=0;for(int j=2;j<=i;j++){if(pd[i-1][j-1]==1) fl=1;if(pd[i-1][j-1]==1&&(a[j]-a[j-1])==(a[i]-a[i-1])) pd[i][j]=1;}if(a[1]<=a[i]-a[i-1]&&fl) pd[i][1]=1;for(int j=1;j<i;j++)if(pd[i][j]==1) flag[i]=1;}Matrix A(kk,kk),res(1,kk);for(int i=1;i<=kk;i++){if(flag[i]==0){A.g[i][1]=max(m-a[1]+1,0);A.f[i][1]=max(Sum(a[1],m),0);} }for(int i=1;i<kk;i++){if(a[i+1]-a[i]<=m){A.g[i][i+1]=1;A.f[i][i+1]=a[i+1]-a[i];}}res.g[1][1]=max(m-a[1]+1,0);res.f[1][1]=max(Sum(a[1],m),0);int b=n-1;while(b){if(b&1) res=res*A;b>>=1;A=A*A;}for(int i=1;i<=kk;i++){if(flag[i]==0) ans=(ans+res.f[1][i])%mod;}printf("%d\n",ans);return 0; }

總結

以上是生活随笔為你收集整理的[CSA49G][XSY3315] Bunny on Number Line (DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

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