题目链接


问题分析

首先一个显然的做法就是建出AC自动机,然后高斯消元。但是这样的复杂度是\(O(n^3m^3)\)的。

我们发现其实只需要求AC自动机上\(n\)个状态的概率,而其余的概率是没有用的。我们不妨设\(i\)赢的概率是\(P_i\)。同时,我们令\(P_0\)为没有任何一个人赢的概率。

然后我们考虑从\(P_0\)转移到\(P_i\)。如果我们直接在\(P_0\)后面加上串\(i\)是可以的。这样的概率是\(\frac{1}{2^m}P_0\)。

但是这样有一个问题:

我们从\(P_0\)转移到\(P_i\)的过程中,可能先转移到了\(P_j\)。比如说,我们在\(P_0\)后加了\(k(0 < k < m)\)位就到了\(j\)。这种情况下,串\(i\)长度为\(k\)的前缀就等于串\(j\)长度为\(k\)的后缀。此时就相当于在\(P_j\)后接一个长为\(m-k\)的串到\(P_i\),而这样的概率是\(\frac{1}{2^{m-k}}P_j\)。

可以借助下图加深理解:

所以我们可以得到\(n\)个方程

\[P_i=\frac{1}{2^m}P_0-\sum_{j=1}^n\sum_{k=1}^m[substr(i,1,k)=substr(j,m-k+1)]\frac{1}{2^{m-k}}P_j
\]

其中\(substr(i,j,k)\)表示串\(i\)从\(j\)到\(k\)所构成的子串。

然后还有\(\sum\limits_{i=1}^nP_i=1\),这样我们就有\(n+1\)个未知数,\(n+1\)个方程。然后你就稳了。

参考程序

#include <bits/stdc++.h>
using namespace std; const int Maxn = 310;
int n, m, A[ Maxn ][ Maxn ], Fail[ Maxn ][ Maxn ];
long double Pow[ Maxn ], B[ Maxn ][ Maxn ]; int main() {
scanf( "%d%d", &n, &m );
for( int i = 1; i <= n; ++i ) {
char Ch[ Maxn ];
scanf( "%s", Ch + 1 );
for( int j = 1; j <= m; ++j )
A[ i ][ j ] = ( Ch[ j ] == 'T' ) ? 1 : 0;
}
for( int i = 1; i <= n; ++i ) {
Fail[ i ][ 1 ] = 0;
int t = 0;
for( int j = 1; j < m; ++j ) {
while( t && A[ i ][ t + 1 ] != A[ i ][ j + 1 ] ) t = Fail[ i ][ t ];
if( A[ i ][ t + 1 ] == A[ i ][ j + 1 ] ) ++t;
Fail[ i ][ j + 1 ] = t;
}
}
Pow[ 0 ] = 1;
for( int i = 1; i <= m; ++i )
Pow[ i ] = Pow[ i - 1 ] * 0.5L; for( int i = 1; i <= n; ++i )
for( int j = 1; j <= n; ++j ) {
B[ i ][ j ] = 0ll;
int t = 0;
for( int k = 1; k <= m; ++k ) {
while( t && A[ i ][ t + 1 ] != A[ j ][ k ] ) t = Fail[ i ][ t ];
if( A[ i ][ t + 1 ] == A[ j ][ k ] ) ++t;
}
if( i == j ) t = Fail[ i ][ t ];//注意不要漏掉这句
while( t ) {
B[ i ][ j ] += Pow[ m - t ];
t = Fail[ i ][ t ];
}
}
for( int i = 1; i <= n; ++i ) {
B[ i ][ 0 ] = -Pow[ m ];
B[ i ][ i ] += 1ll;
}
for( int i = 1; i <= n; ++i ) B[ 0 ][ i ] = 1;
B[ 0 ][ n + 1 ] = 1; for( int i = 0; i <= n; ++i ) {
if( B[ i ][ i ] == 0ll )
for( int j = i + 1; j <= n; ++j ) {
if( B[ j ][ i ] )
for( int k = 0; k <= n + 1; ++k )
swap( B[ i ][ k ], B[ j ][ k ] );
break;
}
long double t = B[ i ][ i ];
for( int j = 0; j <= n + 1; ++j ) B[ i ][ j ] /= t;
for( int j = 0; j <= n; ++j ) {
if( j == i ) continue;
long double T = B[ j ][ i ];
for( int k = 0; k <= n + 1; ++k )
B[ j ][ k ] -= B[ i ][ k ] * T;
}
}
for( int i = 1; i <= n; ++i )
printf( "%.10Lf\n", B[ i ][ n + 1 ] );
return 0;
}

「SDOI2017」硬币游戏的更多相关文章

  1. @loj - 2004@ 「SDOI2017」硬币游戏

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数 ...

  2. 题解 「SDOI2017」硬币游戏

    题目传送门 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利. 大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了. 同学们觉得要加强 ...

  3. 【LOJ 2004】「SDOI2017」硬币游戏

    LOJ 2004 100pts 首先我们肯定要建AC自动机的.. 那么这题就肯定是个AC自动机上\(dp\). 所以想想状态. 首先如果我们把状态设成这样行不行: \(dp(i)\)表示匹配到了i节点 ...

  4. 【LOJ】#2067. 「SDOI2016」硬币游戏

    题解 c一样的就是一个独立的游戏 我们对于2和3的指数 sg[i][j] 表示\(c \cdot 2^i \cdot 3^j\)的棋子,只有这个硬币是反面,翻转的硬币是正面的sg值 枚举sg函数所有可 ...

  5. 「SDOI2017」树点涂色 解题报告

    「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...

  6. LibreOJ 2003. 「SDOI2017」新生舞会 基础01分数规划 最大权匹配

    #2003. 「SDOI2017」新生舞会 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  7. AC日记——「SDOI2017」序列计数 LibreOJ 2002

    「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 201704 ...

  8. 【LOJ】#2269. 「SDOI2017」切树游戏

    题解 把所有的数组一开始就FWT好然后再IFWT回去可以减小常数 从13s跑到0.7s-- 可以参照immortalCO的论文,感受一下毒瘤的动态动态DP 就是用数据结构维护线性递推的矩阵的乘积 由于 ...

  9. loj#2269. 「SDOI2017」切树游戏

    还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...

随机推荐

  1. 使用idea关联mysql时报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/liuqiker/article/detai ...

  2. 坦克大战--Java类型 ---- (3)实现socket通信

    一.实现思路 使用socket通信的一些方法来实现socket通信,客户端和服务端两边需要约定好通信的接口Port(尽量选高的),客户端需要服务端的IP地址,以实现数据交流. 同时,客户端和服务端需要 ...

  3. 喝奶茶最大值(不能喝自己班级的)2019 Multi-University Training Contest 8--hdu杭电第8场(Roundgod and Milk Tea)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6667 题意: 有 n个班级,每个班级有a个人.b个奶茶,每个班的人不能喝自己的奶茶,只能喝别人班的奶茶 ...

  4. 04: redis集群

    1.1 主从同步 1.CPA原理 1. CPA原理是分布式存储理论的基石: C(一致性):   A(可用性):  P(分区容忍性); 2. 当主从网络无法连通时,修改操作无法同步到节点,所以“一致性” ...

  5. EM 算法(三)-GMM

    高斯混合模型 混合模型,顾名思义就是几个概率分布密度混合在一起,而高斯混合模型是最常见的混合模型: GMM,全称 Gaussian Mixture Model,中文名高斯混合模型,也就是由多个高斯分布 ...

  6. C# 面向对象8 值类型和引用类型

    值类型和引用类型 概念 示意图: 1.值类型,在栈中开辟一块空间,存储 2.引用类型,在堆中开辟一块空间,存储数据,然在栈中开辟一块空间存储堆中的数据的地址

  7. Git提交代码的小知识

    1.需要切换到项目目录下并创建一个Repository用于提交代码到这个仓库里 cd /g/....//cd后面有空格,用于进入某个项目文件夹 git init//用于创建Repository 2.添 ...

  8. python字典保存至json文件

    import os import json class SaveJson(object): def save_file(self, path, item): # 先将字典对象转化为可写入文本的字符串 ...

  9. 13 UA池和代理池

    一. 下载中间件 框架图 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器过程中, 下载中间件可以对请 ...

  10. ubuntu自己定义环境变量,替代常用的操作命令

    问题背景是这样的,因为自己会经常用自己的用户链接服务器,比如自己的用户是yongjie,然后服务器的ip是162.105.97.31 所以经常执行的命令是ssh yongjie@162.105.97. ...