P4548 [CTSC2006]歌唱王国
P4548 [CTSC2006]歌唱王國
題目描述
Solution
這一題在《具體數(shù)學(xué)(混泥土數(shù)學(xué))》里講得很詳細(xì)了啊,這里相當(dāng)于總結(jié)一下,想具體了解的直接看書吧。
我們先考慮字符集為222的情況,設(shè)硬幣正面朝上(H)(H)(H)的概率為ppp,反面朝上(T)(T)(T)的概率為qqq。
這道題顯然需要建立一個(gè)類似KMPKMPKMP的自動(dòng)機(jī),令SiS_iSi?表示已經(jīng)到達(dá)目標(biāo)串的第iii個(gè)位置的狀態(tài)集合。
例如目標(biāo)串為THTTHTHTTHTHTTH(以下都以這個(gè)串為例介紹這種做法),則
S2={TH,TTH,HTH,TTTH......}S5={THTTH,TTHTTH,HTHTTH......}S_2=\{TH,TTH,HTH,TTTH......\}\\ S_5=\{THTTH,TTHTTH,HTHTTH......\} S2?={TH,TTH,HTH,TTTH......}S5?={THTTH,TTHTTH,HTHTTH......}
顯然有:
S0=1+S0H+S1T+S2HS1=S0T+S4TS2=S1H+S3HS3=S2TS4=S3TS5=S4HS_0=1+S_0H+S_1T+S_2H\\ S_1=S_0T+S_4T\\ S_2=S_1H+S_3H\\ S_3=S_2T\\ S_4=S_3T\\ S_5=S_4H\\ S0?=1+S0?H+S1?T+S2?HS1?=S0?T+S4?TS2?=S1?H+S3?HS3?=S2?TS4?=S3?TS5?=S4?H
其中111表示空狀態(tài),像S1HS_1\;HS1?H這種形式表示在S1S_1S1?狀態(tài)集合每一個(gè)元素后面加一個(gè)HHH字符之后的狀態(tài)。
這樣的話,我們就能有一個(gè)O(n3)O(n^3)O(n3)的算法。
令E[x]E[x]E[x]表示達(dá)到目標(biāo)串的第xxx個(gè)位置所需要的字符個(gè)數(shù)的期望,直接按照上面的狀態(tài)轉(zhuǎn)移高斯消元計(jì)算即可。
但這顯然是不夠的。
我們?cè)O(shè)N=∑i<nSi,S=SnN=\sum_{i<n} S_i,S=S_nN=∑i<n?Si?,S=Sn?,表示還沒有目標(biāo)串的所有狀態(tài)集合,考慮用只用SSS和NNN,表示出上面的式子。
于是我們可以推出:
1+N(H+T)=S+N1+N(H+T)=S+N 1+N(H+T)=S+N
因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">1+N1+N1+N加上一個(gè)字符之后的狀態(tài)要么沒達(dá)到目標(biāo),要么達(dá)到目標(biāo),根據(jù)定義顯然SSS和NNN不相交。
并且有:
NTHTTH=S+STTHN\;\;THTTH=S+S\;\;TTH NTHTTH=S+STTH
這一個(gè)式子我理解了很久(QAQQAQQAQ)。。
因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">NNN中的元素加了THTTHTHTTHTHTTH之后一定能達(dá)到目標(biāo)狀態(tài),然而可能NNN中的元素加了THTHTH之后就已經(jīng)達(dá)到目標(biāo),這樣就會(huì)在末尾多一個(gè)TTHTTHTTH,且容易發(fā)現(xiàn)SSS和STTHS\;\;TTHSTTH仍是不相交的。
我們考慮這種加了長度為kkk的目標(biāo)串,就包含目標(biāo)串的條件,顯然是ST[1..k]=ST[n?k+1,k]ST[1..k]=ST[n-k+1,k]ST[1..k]=ST[n?k+1,k],就是說STSTST有一段長度為kkk的BorderBorderBorder。
有了這兩個(gè)式子之后,我們就可以推出:
(1?S)(1?H?T)THTTH=S(1+TTH)(1-S)(1-H-T)\;\;THTTH=S(1+TTH) (1?S)(1?H?T)THTTH=S(1+TTH)
事實(shí)上,這里的SSS,TTT和HHH,就不是單純的狀態(tài)了,這里的SSS已經(jīng)是一個(gè)概率生成函數(shù),而TTT和HHH能夠表示一個(gè)概率生成函數(shù)的轉(zhuǎn)移:
設(shè)G(z)G(z)G(z)為一個(gè)表示拋擲次數(shù)的概率生成函數(shù)。
G(z)=∑iPr(z=i)ziG(z)=\sum_i Pr(z=i)z^i G(z)=i∑?Pr(z=i)zi
其中的zzz就是表示拋擲次數(shù)的形式變?cè)?#xff0c;因?yàn)橄乱粋€(gè)字符為TTT的概率為qqq,為HHH的概率為ppp,所以加一個(gè)TTT相當(dāng)于G(z)?pzG(z)*pzG(z)?pz,加一個(gè)HHH相當(dāng)于G(z)?qzG(z)*qzG(z)?qz。
于是上式變成了
(1?G(z))(q?pz?qz)?1p3q2z5=G(z)(1+p2qz)(1-G(z))(q-pz-qz)^{-1}p^3q^2z^5=G(z)(1+p^2qz) (1?G(z))(q?pz?qz)?1p3q2z5=G(z)(1+p2qz)
解得:
G(z)=p3q2z5(1+p2qz3)(1?z)+p3q2z5G(z)=\frac{p^3q^2z^5}{(1+p^2qz^3)(1-z)+p^3q^2z^5} G(z)=(1+p2qz3)(1?z)+p3q2z5p3q2z5?
而我們要求的期望為E(x)=G′(1)E(x)=G'(1)E(x)=G′(1),因此我們需要想方法求出G′(1)G'(1)G′(1)。
有一個(gè)特殊的方法是:
設(shè)
F(z)=z5/G(z)F(z)=z^5/G(z) F(z)=z5/G(z)
可以證明F(z)F(z)F(z)的均值(MeanMeanMean)和G(z)G(z)G(z)的均值相同。
因此Mean(G)=Mean(z5)?Mean(F)=p?1q?1+p?3q?2Mean(G)=Mean(z^5)-Mean(F)=p^{-1}q^{-1}+p^{-3}q^{-2}Mean(G)=Mean(z5)?Mean(F)=p?1q?1+p?3q?2
若p=q=1/2p=q=1/2p=q=1/2,則有期望666次到達(dá)目標(biāo)串。
而根據(jù)上面的式子,容易知道,若存在一個(gè)BorderBorderBorder有xxx個(gè)HHH,yyy個(gè)TTT,則答案Ans+=p?yq?xAns+=p^{-y}q^{-x}Ans+=p?yq?x,所以只要知道有哪些長度的Border,Border,Border,就能算出答案。
我們已經(jīng)解決了字符集大小為222的問題,現(xiàn)在字符集大小為nnn的做法也是一樣的,因?yàn)檫@里的所有字符等概率出現(xiàn),所以就不需要繼續(xù)推到,相當(dāng)于每出現(xiàn)一個(gè)BorderBorderBorder的貢獻(xiàn)為nkn^knk,直接統(tǒng)計(jì)BorderBorderBorder長度,計(jì)算貢獻(xiàn)和即可。
時(shí)間復(fù)雜度O(n)O(n)O(n),有點(diǎn)小精度問題,我開longdouble,WAlong\;\;double,WAlongdouble,WA開double,ACdouble,ACdouble,AC,表示一臉懵逼。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int Mod=10000; const int mods=1e9+7; const int MAXN=600005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } int Pow[MAXN],hsh[MAXN],a[MAXN]; inline int upd(int x,int y,int mods){ return x+y>=mods?x+y-mods:x+y; } inline int gethash(int l,int r) { return upd(hsh[r],mods-1ll*Pow[r-l+1]*hsh[l-1]%mods,mods); } int main() {int C=read(),Case=read();while (Case--){int n=read();for (int i=1;i<=n;i++) a[i]=read();Pow[0]=1;for (int i=1;i<=n;i++) Pow[i]=1ll*Pow[i-1]*(C+1)%mods;for (int i=1;i<=n;i++) hsh[i]=(1ll*hsh[i-1]*(C+1)+a[i])%mods;int ans=0;for (int i=1,p=C%Mod;i<=n;i++,p=p*C%Mod)if (gethash(1,i)==gethash(n-i+1,n)) ans=upd(ans,p,Mod);printf("%04d\n",ans);}return 0; }總結(jié)
以上是生活随笔為你收集整理的P4548 [CTSC2006]歌唱王国的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模板怎么上传(醒图模板怎么上传)
- 下一篇: SRM614 Div1 Hard