Description
周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利。
大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了。
同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况。
用\(H\)表示正面朝上, 用\(T\)表示反面朝上,扔很多次硬币后,会得到一个硬币序列。比如\(HTT\)表示第一次正面朝上,后两次反面朝上。
但扔到什么时候停止呢?大家提议,选出\(n\)个同学, 每个同学猜一个长度为\(m\)的序列,当某一个同学猜的序列在硬币序列中出现时,就不再扔硬币了,并且这个同学胜利。为了保证只有一个同学胜利,同学们猜的\(n\)个序列两两不同。
很快,\(n\)个同学猜好序列,然后进入了紧张而又刺激的扔硬币环节。你想知道,如果硬币正反面朝上的概率相同,每个同学胜利的概率是多少。
第一行两个数 \(n\)、\(m\)。
接下来\(n\)行,每行一个长度为\(m\)的字符串,表示第\(i\)个同学猜的序列。
Output
输出\(n\)行,第\(i\)行表示第\(i\)个同学胜利的概率。选手输出与标准输出的绝对误差不超过\(10^{-6}\)即为正确。
3 3
THT
TTH
HTT
Sample Output
0.3333333333
0.2500000000
0.4166666667
HINT
对于\(10\%\)的数据,\(1\leqslant n,m\leqslant 3\);
对于\(30\%\)的数据,\(1\leqslant n,m\leqslant 18\);
对于另外\(20\%\)的数据,\(n=2\);
对于\(100\%\)的数据,\(1\leqslant n,m\leqslant 300\)。
我们记\(P_i\)为第\(i\)名学生获胜的概率,同时我们会发现,可能存在某些序列是所有同学都没有猜对的。那么我们记\(P_0\)为没人获胜的概率。
很显然,我们从任意一个\(P_0\)串末尾加上串\(i\),这样\(i\)就获胜了,所以有\(P_i=\frac{1}{2^m}P_0\)
但这样存在一个问题,我们从\(P_0\)转移到\(P_i\)的时候,可能会转移到\(P_j\),再转移到\(P_i\)。如过串\(i\)的长度为\(k\)的前缀等于串\(j\)的后缀,那么我们可能在\(P_0\)后加上\(k\)位就到了\(j\),再接上长为\(m-k\)的串得到\(i\),此时的概率为\(\frac{1}{2^{m-k}}P_j\)
即:
\[P_i=\frac{1}{2^m}P_0-\sum\limits_{j=1}^n\sum\limits_{k=1}^m[\mathrm{prefix}(i,k)==\mathrm{suffix}(j,k)]\frac{1}{2^{m-k}}P_j
\]
其中,\(\mathrm{prefix}(i,k)\)表示串\(i\)长度为\(k\)的前缀,\(\mathrm{suffix}(j,k)\)表示串\(j\)长度为\(k\)的后缀。
怎么统计?每个串跑个KMP,暴力判断就行。
然后,为了统计\(P_i\)占\(\sum\limits_{i=1}^nP_i\)的概率,我们加一个\(\sum\limits_{i=1}^nP_i=1\)即可
那这样就有\(n+1\)个变量,\(n+1\)个方程,高斯消元就好了。
/*program from Wolfycz*/
#include