「SDOI2017」硬币游戏
问题分析
首先一个显然的做法就是建出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\)个方程
\]
其中\(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」硬币游戏的更多相关文章
- @loj - 2004@ 「SDOI2017」硬币游戏
目录 @description@ @solution@ @accepted code@ @details@ @description@ 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数 ...
- 题解 「SDOI2017」硬币游戏
题目传送门 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利. 大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了. 同学们觉得要加强 ...
- 【LOJ 2004】「SDOI2017」硬币游戏
LOJ 2004 100pts 首先我们肯定要建AC自动机的.. 那么这题就肯定是个AC自动机上\(dp\). 所以想想状态. 首先如果我们把状态设成这样行不行: \(dp(i)\)表示匹配到了i节点 ...
- 【LOJ】#2067. 「SDOI2016」硬币游戏
题解 c一样的就是一个独立的游戏 我们对于2和3的指数 sg[i][j] 表示\(c \cdot 2^i \cdot 3^j\)的棋子,只有这个硬币是反面,翻转的硬币是正面的sg值 枚举sg函数所有可 ...
- 「SDOI2017」树点涂色 解题报告
「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...
- LibreOJ 2003. 「SDOI2017」新生舞会 基础01分数规划 最大权匹配
#2003. 「SDOI2017」新生舞会 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- AC日记——「SDOI2017」序列计数 LibreOJ 2002
「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 201704 ...
- 【LOJ】#2269. 「SDOI2017」切树游戏
题解 把所有的数组一开始就FWT好然后再IFWT回去可以减小常数 从13s跑到0.7s-- 可以参照immortalCO的论文,感受一下毒瘤的动态动态DP 就是用数据结构维护线性递推的矩阵的乘积 由于 ...
- loj#2269. 「SDOI2017」切树游戏
还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...
随机推荐
- 使用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 ...
- 坦克大战--Java类型 ---- (3)实现socket通信
一.实现思路 使用socket通信的一些方法来实现socket通信,客户端和服务端两边需要约定好通信的接口Port(尽量选高的),客户端需要服务端的IP地址,以实现数据交流. 同时,客户端和服务端需要 ...
- 喝奶茶最大值(不能喝自己班级的)2019 Multi-University Training Contest 8--hdu杭电第8场(Roundgod and Milk Tea)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6667 题意: 有 n个班级,每个班级有a个人.b个奶茶,每个班的人不能喝自己的奶茶,只能喝别人班的奶茶 ...
- 04: redis集群
1.1 主从同步 1.CPA原理 1. CPA原理是分布式存储理论的基石: C(一致性): A(可用性): P(分区容忍性); 2. 当主从网络无法连通时,修改操作无法同步到节点,所以“一致性” ...
- EM 算法(三)-GMM
高斯混合模型 混合模型,顾名思义就是几个概率分布密度混合在一起,而高斯混合模型是最常见的混合模型: GMM,全称 Gaussian Mixture Model,中文名高斯混合模型,也就是由多个高斯分布 ...
- C# 面向对象8 值类型和引用类型
值类型和引用类型 概念 示意图: 1.值类型,在栈中开辟一块空间,存储 2.引用类型,在堆中开辟一块空间,存储数据,然在栈中开辟一块空间存储堆中的数据的地址
- Git提交代码的小知识
1.需要切换到项目目录下并创建一个Repository用于提交代码到这个仓库里 cd /g/....//cd后面有空格,用于进入某个项目文件夹 git init//用于创建Repository 2.添 ...
- python字典保存至json文件
import os import json class SaveJson(object): def save_file(self, path, item): # 先将字典对象转化为可写入文本的字符串 ...
- 13 UA池和代理池
一. 下载中间件 框架图 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器过程中, 下载中间件可以对请 ...
- ubuntu自己定义环境变量,替代常用的操作命令
问题背景是这样的,因为自己会经常用自己的用户链接服务器,比如自己的用户是yongjie,然后服务器的ip是162.105.97.31 所以经常执行的命令是ssh yongjie@162.105.97. ...