BZOJ 4820 Sdoi2017 硬幣遊戲

2022-04-02 22:03:48 字數 2315 閱讀 4601

好仙的題目啊,本來是kmp裡的題但最後該用的地方被我用hash艹過去了算了反正這不是這道題的重點

考慮乙個暴力的\(o((nm)^3)\)的做法,其實就是bzoj 1444: [jsoi2009]有趣的遊戲的弱化版,但在這道題中直接上只能得到40pts

我們考慮一下這個方法為什麼不行,其實主要的原因是狀態實在太多了

考慮到實際上有意義的狀態只有\(n\)個,其餘的狀態都可以合併成乙個——「不合法的狀態」

乍一看是不是很亂來?怎麼能把那麼多不同的狀態歸為一類?

沒事我們來找個情況分析一下,在這之前先放乙個顯然的引理:

引理:構造乙個指定的長度為\(l\)的\(01\)串的概率是\(\frac\)

考慮現在\(s\)是乙個不合法的狀態(即沒有人獲勝),\(a=101\),\(b=110\)

那麼我們假定遊戲進行到到\(s+101\)的狀態,那麼此時遊戲一定會停止,但不一定要等到\(101\)加完才停止

很顯然我們可以看出當\(s\)的字尾是\(1\)或者\(10\)時遊戲會提前結束,換句話說會有這些情況:

\[s+101=(s+a)+(s'+a+01)+(s''+b+1)

\]其中\(s=s'+10=s''+1\)

那麼我們根據上面的引理,可以得到乙個方程:

\[\fracs=a+\fraca+\fracb

\]是不是很神奇,但仔細一想我們發現這確實包含了所有情況,那麼我們來試著形式化一下這鐘方法:

對於每乙個字串\(s_i\),設它獲勝的概率是\(p_i\),不合法(即永遠無法結束)的輔助狀態的概率設為\(s\)

我們發現對於另乙個字串\(s_j\),若\(s_j\)存在長度為\(k\)的字尾能匹配\(s_i\)的字首,那麼就有\(\frac}\)的概率提前結束

那麼我們在設\(pre_\)表示字串\(s_i\)長度為\(j\)的字首,\(suf_\)表示字串\(s_i\)長度為\(j\)的字尾

那麼對於每乙個\(s_i\),我們都將\(s+s_i\)作為一次終止狀態列個方程,即:

\[\sum_^n\sum_^m [pre_=suf_]\frac} p_j=\fracs

\]但這樣只有\(n\)個方程,但變數有\(n+1\)個。我們發現其實遊戲必然會結束,即\(s=0\),所以可以列出最後乙個方程:\(\sum_^n p_i=1\),然後就上高消即可,複雜度\(o(n^3)\)

ps:那個匹配字首字尾可以用kmp,但我比較懶因此寫了hash

pps:這題非常開精度,如果你得到了40pts的好成績請把高消寫成精度更高的方法,並且在bzoj上由於沒有spj,因此eps要調到\(10^\)

#include#include#include#define ri register int

#define ci const int&

using namespace std;

typedef unsigned long long u64;

const int n=305;

const double eps=1e-10;

struct hasher

friend inline bool operator == (const hasher& a,const hasher& b)

friend inline hasher operator + (const hasher& a,const hasher& b)

friend inline hasher operator * (const hasher& a,const hasher& b)

}pw[n],pre[n][n],suf[n][n]; int n,m; double pw2[n],p[n][n],val[n]; char s[n];

const hasher seed=hasher(233,167);

inline void gauss(ci n)

}for (val[n]/=p[n][n],i=n-1;i;--i)

}int main()

for (i=1;i<=n;++i) for (j=1;j<=n;++j) for (k=1;k<=m;++k)

if (pre[i][k]==suf[j][m-k+1]) p[i][j]+=pw2[m-k];

for (i=1;i<=n;++i) p[i][n+1]=-pw2[m],p[n+1][i]=1; val[n+1]=1;

for (gauss(n+1),i=1;i<=n;++i) printf("%.10lf\n",val[i]);

return 0;

}

bzoj 4820 硬幣遊戲

週末同學們非常無聊,有人提議,咱們扔硬幣玩吧,誰扔的硬幣正面次數多誰勝利。大家紛紛覺得這個遊戲非常符 合同學們的特色,但只是扔硬幣實在是太單調了。同學們覺得要加強趣味性,所以要找乙個同學扔很多很多次硬幣 其他同學記錄下正反面情況。用h表示正面朝上,用t表示反面朝上,扔很多次硬幣後,會得到乙個硬幣序列...

Bzoj 2726 SDOI 任務安排

memory limit 131072kb 64bit io format lld llu description 機器上有n個需要處理的任務,它們構成了乙個序列。這些任務被標號為1到n,因此序列的排列為1,2,3.n。這n個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工...

BZOJ 3991 SDOI2015 尋寶遊戲

題目大意 給定一棵樹,其中有若干個關鍵點,任意選擇起點,求從起點出發訪問所有關鍵點又回到起點的最小邊權總和,有m個修改操作,每次修改乙個關鍵點。假如沒有修改操作的話,就像乙個簡單的樹形dp,方程如下 f i sigma sigma.觀察一下dp的過程,就是不斷地從前面的點走到後面的點,所以我們可以不...