【BZOJ4820】[Sdoi2017]硬币游戏

Description

周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利。大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了。同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况。用H表示正面朝上,用T表示反面朝上,扔很多次硬币后,会得到一个硬币序列。比如HTT表示第一次正面朝上,后两次反面朝上。但扔到什么时候停止呢?大家提议,选出n个同学,每个同学猜一个长度为m的序列,当某一个同学猜的序列在硬币序列中出现时,就不再扔硬币了,并且这个同学胜利,为了保证只有一个同学胜利,同学们猜的n个序列两两不同。很快,n个同学猜好序列,然后进入了紧张而又刺激的扔硬币环节。你想知道,如果硬币正反面朝上的概率相同,每个同学胜利的概率是多少。

Input

第一行两个整数n,m。
接下里n行,每行一个长度为m的字符串,表示第i个同学猜的序列。
1<=n,m<=300

Output

输出n行,第i行表示第i个同学胜利的概率。
输出与标准输出的绝对误差不超过10^-6即视为正确。

Sample Input

3 3
THT
TTH
HTT

Sample Output

0.3333333333
0.2500000000
0.4166666667

题解:网上看了好多题解都很难懂,我换一种理解方式来说吧~

我们设与所有字符串都不匹配的串的期望长度为N,同时,期望长度也可以表示每个串的期望经过次数,因为所有串的期望经过次数之和为1,那么它也可以用来表示每个人获胜的概率。具体的说,每一个跟所有串都不匹配的串出现的概率都是相同的,它们的和就是N。(这几句话是做这道题的先决条件。)

枚举每个字符串,设当前枚举到A,我们在N后面强行加上一个串A,形成NA,它出现的概率自然就是${N\over 2^m}$,那么它是不是就是A获胜的概率呢?显然不是。因为N的后缀是不确定的,在强行加上串A时,它有可能提前形成了别的串(或者提前形成了串A本身),那么NA的概率自然就是这些情况发生的概率之和。具体地,如果:A的x前缀是B的x后缀,那么N的m-x后缀就是B的前缀,它发生的概率为$1\over 2^{m-x}$,所以当我们在AC自动机上找出所有这样的B和x后,就能得到:

$P_{NA}={P_N\over 2^m}=\sum{P_B\over 2^{m-x}}+P_A$

此外,我们还有方程$\sum Pi=1$,所以就有n+1个未知数和n+1个方程,高斯消元就好了

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <cmath>
  5. #include <queue>
  6. using namespace std;
  7. typedef long double ld;
  8. const ld eps=1e-10;
  9. int n,m,tot;
  10. int pos[310],dep[90010];
  11. struct acm
  12. {
  13. int ch[2],fail,dan;
  14. }p[90010];
  15. char str[310][310];
  16. ld v[310][310],m2[310];
  17. queue<int> q;
  18. void build()
  19. {
  20. int i,u;
  21. q.push(1);
  22. while(!q.empty())
  23. {
  24. u=q.front(),q.pop();
  25. for(i=0;i<=1;i++)
  26. {
  27. if(!p[u].ch[i])
  28. {
  29. if(u==1) p[u].ch[i]=1;
  30. else p[u].ch[i]=p[p[u].fail].ch[i];
  31. continue;
  32. }
  33. q.push(p[u].ch[i]);
  34. if(u==1) p[p[u].ch[i]].fail=1;
  35. else p[p[u].ch[i]].fail=p[p[u].fail].ch[i];
  36. }
  37. }
  38. }
  39. void gauss()
  40. {
  41. int i,j,k; ld t;
  42. n++;
  43. for(i=1;i<=n;i++)
  44. {
  45. for(j=i;j<=n;j++) if(fabs(v[j][i])>fabs(v[i][i])) for(k=1;k<=n+1;k++) swap(v[i][k],v[j][k]);
  46. t=v[i][i];
  47. for(k=i;k<=n+1;k++) v[i][k]/=t;
  48. for(j=1;j<=n;j++) if(i!=j)
  49. {
  50. t=v[j][i];
  51. for(k=1;k<=n+1;k++) v[j][k]-=t*v[i][k];
  52. }
  53. }
  54. n--;
  55. }
  56. int main()
  57. {
  58. scanf("%d%d",&n,&m);
  59. int i,j,u,a,t;
  60. for(m2[0]=1.0,i=1;i<=m;i++) m2[i]=m2[i-1]*0.5;
  61. for(tot=i=1;i<=n;i++)
  62. {
  63. scanf("%s",str[i]);
  64. for(u=1,j=0;j<m;j++)
  65. {
  66. a=(str[i][j]=='T');
  67. if(!p[u].ch[a]) p[u].ch[a]=++tot;
  68. u=p[u].ch[a];
  69. }
  70. p[u].dan=i,pos[i]=u;
  71. }
  72. build();
  73. for(i=1;i<=n;i++)
  74. {
  75. for(u=1,j=0;j<m;j++) u=p[u].ch[str[i][j]=='T'],dep[u]=j+1;
  76. v[i][n+1]=m2[m];
  77. for(j=1;j<=n;j++) for(t=pos[j];t;t=p[t].fail) if(dep[t]) v[i][j]+=m2[m-dep[t]];
  78. for(u=1,j=0;j<m;j++) u=p[u].ch[str[i][j]=='T'],dep[u]=0;
  79. }
  80. for(i=1;i<=n;i++) v[n+1][i]=1;
  81. v[n+1][n+2]=1;
  82. gauss();
  83. for(i=1;i<=n;i++) printf("%.10lf\n",(double)v[i][n+2]);
  84. return 0;
  85. }

【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元的更多相关文章

  1. 2016ACM/ICPC亚洲区沈阳站H - Guessing the Dice Roll HDU - 5955 ac自动机+概率dp+高斯消元

    http://acm.hdu.edu.cn/showproblem.php?pid=5955 题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少 题解:先建成ac ...

  2. 4.23 子串 AC自动机 概率期望 高斯消元

    考虑40分. 设出状态 f[i]表示匹配到了i位还有多少期望长度能停止.可以发现这个状态有环 需要高斯消元. 提供一种比较简单的方法:由于期望的线性可加性 可以设状态f[i]表示由匹配到i到匹配到i+ ...

  3. BZOJ_1778_[Usaco2010 Hol]Dotp 驱逐猪猡_概率DP+高斯消元

    BZOJ_1778_[Usaco2010 Hol]Dotp 驱逐猪猡_概率DP+高斯消元 题意: 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 3 ...

  4. LightOJ - 1151概率dp+高斯消元

    概率dp+高斯消元 https://vjudge.net/problem/LightOJ-1151 题意:刚开始在1,要走到100,每次走的距离1-6,超过100重来,有一些点可能有传送点,可以传送到 ...

  5. 【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元

    题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两 ...

  6. BZOJ3270 博物館 概率DP 高斯消元

    BZOJ3270 博物館 概率DP 高斯消元 @(XSY)[概率DP, 高斯消元] Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博 ...

  7. BZOJ 3270: 博物馆 [概率DP 高斯消元]

    http://www.lydsy.com/JudgeOnline/problem.php?id=3270 题意:一张无向图,一开始两人分别在$x$和$y$,每一分钟在点$i$不走的概率为$p[i]$, ...

  8. 【BZOJ3640】JC的小苹果 概率DP+高斯消元

    [BZOJ3640]JC的小苹果 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话说JC历经艰辛来到了城市B,但 ...

  9. hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】

    含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...

随机推荐

  1. 基于Redis的Bloomfilter去重(转载)

    转载:http://blog.csdn.net/bone_ace/article/details/53107018 前言 “去重”是日常工作中会经常用到的一项技能,在爬虫领域更是常用,并且规模一般都比 ...

  2. Java程序中的Log文件配置

    log4j.properties文件 log4j.rootLogger=info,stdout,logfile #stdout log4j.appender.stdout=org.apache.log ...

  3. linux下c,c++头文件的路径

    一. C语言包含的目录: 二. C++包含的目录

  4. 关于八数码问题中的状态判重的三种解决方法(编码、hash、&lt;set&gt;)

    八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...

  5. Nmon命令行:Linux系统性能的监测利器

    如果你眼下正在寻找一款非常易于使用的Linux性能监测工具,那么我强烈推荐安装和使用Nmon命令行实用工具. Nmon监测工具 Nmon是一款面向系统管理员的调优和基准测量工具,可以用来显示关于下列方 ...

  6. shell 命令行语句

    第一步:ssh免密码登陆[用公钥,私钥] 第二步: #!/bin/bash while read server;do ssh -n $server >& |sed "s/^/$ ...

  7. kettle入门(七) 之kettle增量方案(一)全量比对取增量-依据唯一标示

    引: ods有个project表来自于上游系统,数据量不大 十几万,下游系统须要此数据,而且须要每天提供截止当天的增量数据 要求每条数据给出数据变化时间及标示,即数据若是插入 有插入时间和插入标示 若 ...

  8. 网上流传的长盛不衰的Steve Jobs(乔布斯) 14分钟“Stay Hungry, Stay Foolish”演讲视频

    http://timyang.net/misc/speech/附:网上流传的长盛不衰的Steve Jobs 14分钟“Stay Hungry, Stay Foolish”演讲视频 (原视频地址:htt ...

  9. 【Lucene】Apache Lucene全文检索引擎架构之搜索功能3

    上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开 ...

  10. python 三个双引号

    有的内容被上面三个双引号和下面三个双引号包围了,这些内容不执行.即,下面aaa的部分不执行. """ aaaa; """