1444: [Jsoi2009]有趣的游戏

链接

分析:

  如果一个点回到0号点,那么会使0号点的概率增加,而0号点的概率本来是1,不能增加,所以这题用期望做。

  设$x_i$表示经过i的期望次数,然后初始可以知道$x_0=0$,又因为末尾节点只会经过一次,所以末尾节点的概率就是期望。

  然后建出AC自动机,高斯消元。

  参考sengxian

代码:

Gauss

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<cmath>
  6. #include<cctype>
  7. #include<set>
  8. #include<queue>
  9. #include<vector>
  10. #include<map>
  11. using namespace std;
  12. typedef long long LL;
  13.  
  14. inline int read() {
  15. int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
  16. for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
  17. }
  18.  
  19. const int N = ;
  20. const double eps = 1e-;
  21. int ch[N][], val[N], fail[N], id[N], q[N], Index;
  22. int n, L, m;
  23. char s[N];
  24. double A[N][N], p[N];
  25.  
  26. void Insert(int x) {
  27. int now = ;
  28. for (int i = ; i < L; ++i) {
  29. int c = s[i] - 'A';
  30. if (!ch[now][c]) ch[now][c] = ++Index;
  31. now = ch[now][c];
  32. }
  33. val[now] = , id[x] = now;
  34. }
  35. void bfs() {
  36. int L = , R = ;
  37. for (int c = ; c < m; ++c) if (ch[][c]) q[++R] = ch[][c];
  38. while (L <= R) {
  39. int u = q[L ++];
  40. for (int c = ; c < m; ++c) {
  41. int v = ch[u][c];
  42. if (!v) ch[u][c] = ch[fail[u]][c];
  43. else {
  44. fail[v] = ch[fail[u]][c];
  45. val[v] |= val[fail[v]];
  46. q[++R] = v;
  47. }
  48. }
  49. }
  50. }
  51. bool Gauss(int n) {
  52. for (int k = ; k <= n; ++k) {
  53. int r = k;
  54. for (int i = k + ; i <= n; ++i) if (A[i][k] > A[r][k]) r = k;
  55. if (r != k) for (int j = ; j <= n + ; ++j) swap(A[r][j], A[k][j]);
  56. for (int i = k + ; i <= n; ++i) {
  57. if (fabs(A[i][k]) > eps) {
  58. double t = A[i][k] / A[k][k];
  59. for (int j = ; j <= n + ; ++j) A[i][j] -= A[k][j] * t;
  60. }
  61. }
  62. }
  63. for (int i = n; i >= ; --i) {
  64. for (int j = i + ; j <= n; ++j) A[i][n + ] -= A[j][n + ] * A[i][j];
  65. A[i][n + ] /= A[i][i];
  66. }
  67. return ;
  68. }
  69. int main() {
  70. n = read(), L = read(), m = read();
  71. for (int i = ; i < m; ++i) {
  72. int u = read(), v = read();
  73. p[i] = 1.0 * u / v;
  74. }
  75. int cnt = ;
  76. for (int i = ; i < n; ++i) {
  77. scanf("%s", s);
  78. for (int j = ; j < L; ++j)
  79. if (p[s[j] - 'A'] <= eps) { cnt ++; break; }
  80. Insert(i);
  81. }
  82. if (cnt == n) {
  83. for (int i = ; i <= n; ++i) puts("0.00"); return ;
  84. }
  85. bfs();
  86. A[][Index + ] = -;
  87. for (int i = ; i <= Index; ++i) {
  88. A[i][i] = -1.0;
  89. if (val[i]) continue;
  90. for (int c = ; c < m; ++c) A[ch[i][c]][i] += p[c];
  91. }
  92. Gauss(Index);
  93. for (int i = ; i < n; ++i) {
  94. double p = A[id[i]][Index + ];
  95. if (fabs(p) <= eps) puts("0.00");
  96. else printf("%.2lf\n", p);
  97. }
  98. return ;
  99. }

迭代+矩阵

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<cmath>
  6. #include<cctype>
  7. #include<set>
  8. #include<queue>
  9. #include<vector>
  10. #include<map>
  11. using namespace std;
  12. typedef long long LL;
  13.  
  14. inline int read() {
  15. int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
  16. for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
  17. }
  18.  
  19. const int N = ;
  20. struct Node {
  21. double a[N][N];
  22. Node() { memset(a, , sizeof(a)); }
  23. } A;
  24. int ch[N][], val[N], fail[N], id[N], q[N], Index;
  25. int n, L, m;
  26. char s[N];
  27. double p[N];
  28.  
  29. Node operator * (const Node &A,const Node &B) {
  30. Node C;
  31. for (int k = ; k <= Index; ++k)
  32. for (int i = ; i <= Index; ++i)
  33. for (int j = ; j <= Index; ++j)
  34. C.a[i][j] += A.a[i][k] * B.a[k][j];
  35. return C;
  36. }
  37. void Insert(int x) {
  38. int now = ;
  39. for (int i = ; i < L; ++i) {
  40. int c = s[i] - 'A';
  41. if (!ch[now][c]) ch[now][c] = ++Index;
  42. now = ch[now][c];
  43. }
  44. val[now] = , id[x] = now;
  45. }
  46. void bfs() {
  47. int L = , R = ;
  48. for (int c = ; c < m; ++c) if (ch[][c]) q[++R] = ch[][c];
  49. while (L <= R) {
  50. int u = q[L ++];
  51. for (int c = ; c < m; ++c) {
  52. int v = ch[u][c];
  53. if (!v) ch[u][c] = ch[fail[u]][c];
  54. else {
  55. fail[v] = ch[fail[u]][c];
  56. val[v] |= val[fail[v]];
  57. q[++R] = v;
  58. }
  59. }
  60. }
  61. }
  62. int main() {
  63. n = read(), L = read(), m = read();
  64. for (int i = ; i < m; ++i) {
  65. int u = read(), v = read();
  66. p[i] = 1.0 * u / v;
  67. }
  68. for (int i = ; i < n; ++i) {
  69. scanf("%s", s);
  70. Insert(i);
  71. }
  72. bfs();
  73. for (int i = ; i <= Index; ++i) {
  74. if (val[i]) A.a[i][i] = ;
  75. else for (int c = ; c < m; ++c) A.a[i][ch[i][c]] += p[c];
  76. }
  77. for (int i = ; i <= ; ++i) A = A * A;
  78. for (int i = ; i < n; ++i) printf("%.2lf\n", A.a[][id[i]]);
  79. return ;
  80. }

1444: [Jsoi2009]有趣的游戏的更多相关文章

  1. BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)

    1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...

  2. BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]

    1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...

  3. BZOJ 1444:[JSOI2009]有趣的游戏

    BZOJ 1444:[JSOI2009]有趣的游戏 题目链接 首先我们建出Trie图,然后高斯消元. 我们设\(f_i\)表示经过第\(i\)个点的期望次数: \[ f_x=\sum i\cdot p ...

  4. BZOJ 1444 [Jsoi2009]有趣的游戏 (AC自动机 + 概率DP + Gauss)

    1444: [Jsoi2009]有趣的游戏 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1382  Solved: 498[Submit][Statu ...

  5. ●BZOJ 1444 [Jsoi2009]有趣的游戏

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1444题解.1: 概率dp,矩阵乘法,快速幂. 对所有串建立AC自动机, 那么如果在trie树 ...

  6. bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】

    https://blog.sengxian.com/solutions/bzoj-1444 orz 一直是我想错了,建出AC自动机之后,实际上这个定义是设f[i]为经过i节点的 * 期望次数 * ,因 ...

  7. BZOJ 1444 [JSOI2009]有趣的游戏 (AC自动机、概率与期望DP、矩阵乘法)

    诶这题洛谷居然没有??? 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1444 题解: 我见到主要有三种做法. 一是矩阵乘法.设\(d ...

  8. BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)

    题目大意:给你$N$个长度相等且互不相同的模式串,现在有一个字符串生成器会不断生成字符,其中每个字符出现的概率是$p_{i}/q_{i}$,当生成器生成的字符串包含了某个模式串,则拥有该模式串的玩家胜 ...

  9. BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机+概率与期望+矩阵乘法

    这道题还比较友好~首先,构建出来 $AC$ 自动机,那么我们要求的就是从 $0$ 号点走无限次走到一个终止节点的概率. 考虑构建转移矩阵 $M,$ $M_{i,j}$ 表示节点 $i$ 转移到节点 $ ...

随机推荐

  1. React:组件的生命周期

    在组件的整个生命周期中,随着该组件的props或者state发生改变,其DOM表现也会有相应的变化.一个组件就是一个状态机,对于特定地输入,它总返回一致的输出. 一个React组件的生命周期分为三个部 ...

  2. .Net 面试题 汇总(四)

    1.简述 private. protected. public. internal 修饰符的访问权限.private : 私有成员, 在类的内部才可以访问.protected : 保护成员,该类内部和 ...

  3. spring mvc 解决跨域问题

    Spring MVC 从4.2版本开始增加了对CORS的支持. 在Controller上使用@CrossOrigin注解: // 指定域名 @CrossOrigin("http://doma ...

  4. 浅析NSTextContainer

    浅析NSTextContainer TextKit中的NSTextContainer有点晦涩难懂,如果想用TextKit实现文本分页的效果,你是必须要使用NSTextContainer的...... ...

  5. 初学Linux(一)关闭操作shutdown halt reboot

    1.shutdown –h 10 #这个命令告诉大家,计算机将在10分钟后关机,并且会显示在登陆用户的当前屏幕中. 2.Shutdown –h now #立马关机 3.Shutdown –h 11:1 ...

  6. Mysql--通俗易懂的左连接、右连接、内连接

    刚开始看书的时候花了好长时间理解 先通俗易懂的描述下: left join(左联接): 返回包括左表中的所有记录和右表中联结字段相等的记录. right join(右联接): 返回包括右表中的所有记录 ...

  7. Hadoop HBase概念学习系列之HBase里的宽表设计概念(表设计)(二十七)

    在下面这篇博文里,我给各位博客们,分享了创建HBase表,但这远不止打好基础. HBase编程 API入门系列之create(管理端而言)(8) 在关系型数据库里,表的高表和宽表是不存在的.在如HBa ...

  8. C#综合揭秘——分部类和分部方法

    在面向对象的“封装闭合性”开发原则中,一向提倡的是把独立的功能封装在一个类里面的!但从Visual Studio 2005开发,系统提供了一个分部类的开发方式一直受到争议,很多人认为把同一类的功能分布 ...

  9. 激活office软件

    1. 打开校园软件正版化激活网址 http://nic.seu.edu.cn/2015/0113/c12333a115290/page.htm 2. 下载KMS激活脚本 3. 登陆easyconnec ...

  10. DXperience 工具箱不显示/ Visual Studio 2012选择项打开崩溃

    1.移除NetFx40_LegacySecurityPolicy  节: 移除C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\I ...