1444: [Jsoi2009]有趣的游戏

4820: [Sdoi2017]硬币游戏

这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题。

第一题数据范围较小,将串建成AC自动机以后,以AC自动机上每个点为一个未知数,列出方程高斯消元求解即可,时间复杂度$O(n^{3}m^{3})$。

#include<queue>
#include<cstdio>
#include<algorithm>
#define MN 21
#define ld double
#define eps 1e-12
using namespace std;struct na{int t[10],bo,f;na(){bo=0;}}t[MN*MN];
int n,m,l,mo[MN],num=0,p[MN],q[MN];
char s[21];
int insert(char s[]){int i=0,j=0;for (;s[i];j=t[j].t[s[i]-'A'],i++)if (!t[j].t[s[i]-'A']) t[j].t[s[i]-'A']=++num;t[j].bo=1;for (i=0;s[i];i++) if (p[s[i]-'A']==0) return -1;return j;
}
queue<int> _q;
ld a[MN*MN][MN*MN],S;
ld abs(ld a){return a<0?-a:a;}
inline void Gauss(){int i,j,k;for (i=0;i<=num;i++){for (j=i;j<=num;j++) if (abs(a[j][i])>eps) break;for (k=0;k<=num+1;k++) swap(a[i][k],a[j][k]);for (j=0;j<=num;j++)if (j!=i)for (S=a[j][i]/a[i][i],k=0;k<=num+1;k++) a[j][k]-=S*a[i][k];}
}
int main(){register int i,j;scanf("%d%d%d",&n,&l,&m);for (i=0;i<m;i++) scanf("%d%d",&p[i],&q[i]);for (i=0;i<n;i++) scanf("%s",s),mo[i]=insert(s);t[0].f=0;for (i=0;i<m;i++) if (t[0].t[i]) _q.push(t[0].t[i]),t[t[0].t[i]].f=0;while (!_q.empty()){int k=_q.front();_q.pop();for (i=0;i<m;i++)if (t[k].t[i]){for (j=t[k].f;j&&!t[j].t[i];j=t[j].f);t[t[k].t[i]].f=t[j].t[i];_q.push(t[k].t[i]);}}for (int k=0;k<=num;a[k][k]-=1.,k++)if (!t[k].bo)for (i=0;i<m;i++){for (j=k;j&&!t[j].t[i];j=t[j].f);j=t[j].t[i];a[j][k]+=1.*p[i]/q[i];}a[0][num+1]=-1;Gauss();for (i=0;i<n;i++) if (mo[i]==-1) puts("0.00");else printf("%.2lf\n",a[mo[i]][num+1]/a[mo[i]][mo[i]]+eps);
}

1444: [Jsoi2009]有趣的游戏

第二题,数据范围较大,直接建AC自动机必定会TLE,所以考虑化简。我们需要的只是n个目标状态的答案,而不需要AC自动机上其他点的答案,那么这些点是否可以合并起来,统一考虑呢?

以样例为例:

$S_1=THT,S_2=TTH,S_3=HTT$

考虑一个状态X,表示所有未达到目标状态的字符串。

那么若在X后面接上一个$S_1$,肯定就到达了目标状态,也可能我们还没填完$S_1$我们就达成了目标状态,这些一起考虑起来,可以得到

$$\frac{X}{2^{3}}=S_1+\frac{S_1}{2^{2}}+\frac{S_2}{2}+\frac{S_3}{2^{2}}$$

这是什么意思?XTHT有可能是以下几种情况(我们用$F_{S_i}$表示$S_i$的出现概率)

XTHT =$F_{S_1}$

YTHT   HT=$F_{S_1}$   HT(X以TH结尾,即X=YTH)

YTTH   T=$F_{S_2}$   T(X以T结尾,即X=YT)

YHTT   HT=$F_{S_2}$   HT(X以HT结尾,即X=YHT)

额外多出来的x个字符就需要花费$\frac{1}{2^{x}}$的概率去生成它,也就很显然地对应了上面的式子。

再考虑在X后面接上$S_2$和$S_3$我们又得到两个方程,再加上$\sumF_{S_i}$,一共4(n+1)个方程,解3(n)个变量刚刚好。

另外如果高斯消元的时候你是用的eps来找第一个非0位置,那么很有可能爆精度,这时候你需要将其修改为找到绝对值最大的位置(虽然不知道为什么这样就可以了)。

#include<queue>
#include<cstdio>
#include<algorithm>
#define MN 321
#define ld double
#define eps 1e-12
using namespace std;int n,m,l,mo[MN],num=0,ne[MN<<1];
char s[MN][MN],c[MN<<1];
ld a[MN][MN],S,two[MN];
ld abs(ld a){return a<0?-a:a;}
inline void Gauss(){int i,j,k;for (i=0;i<=num;i++){for (j=i;j<=num;j++) if (abs(a[j][i])>eps) break;for (k=0;k<=num+1;k++) swap(a[i][k],a[j][k]);for (j=0;j<=num;j++)if (j!=i)for (S=a[j][i]/a[i][i],k=0;k<=num+1;k++) a[j][k]-=S*a[i][k];}
}
int main(){register int i,j,k,l;scanf("%d%d",&n,&m);for (i=1;i<=n;i++) scanf("%s",s[i]);for (two[0]=1,i=1;i<=m;i++) two[i]=two[i-1]*0.5;for (i=1;i<=n;i++)for (a[i][0]=-two[m],j=1;j<=n;j++){for (k=0;k<m;k++) c[k]=s[i][k],c[m+m-k-1]=s[j][m-k-1];c[m+m]=0;ne[0]=-1;for (k=1;k<m+m;ne[k]=l+(c[l+1]==c[k]),k++)for (l=ne[k-1];l!=-1&&c[l+1]!=c[k];l=ne[l]);for (k=ne[k-1];k!=-1;k=ne[k])if (k<m) a[i][j]+=two[m-1-k];}for (i=1;i<=n+1;i++) a[0][i]=1;num=n;Gauss();for (i=1;i<=n;i++) printf("%.8lf\n",a[i][n+1]/a[i][i]+eps);
}

4820: [Sdoi2017]硬币游戏

转载于:https://www.cnblogs.com/Enceladus/p/6724802.html

BZOJ:4820: [Sdoi2017]硬币游戏BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)相关推荐

  1. BZOJ 1444: [Jsoi2009]有趣的游戏

    1444: [Jsoi2009]有趣的游戏 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1114  Solved: 386 [Submit][Sta ...

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

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

  3. BZOJ.4820.[SDOI2017]硬币游戏(思路 高斯消元 哈希/AC自动机/KMP)

    BZOJ 洛谷 建出AC自动机,每个点向两个儿子连边,可以得到一张有向图.参照 [SDOI2012]走迷宫 可以得到一个\(Tarjan\)+高斯消元的\(O((nm)^3)\)的做法.(理论有\(6 ...

  4. bzoj 4820: [Sdoi2017]硬币游戏 概率dp+高斯消元+KMP

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

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

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

  6. [高斯消元 概率 KMP] BZOJ 4820 [Sdoi2017]硬币游戏

    一个直观的想法 是建AC自动机 然后消元 但是这样变量个数是O(nm)O(nm) 然后我就不会做了 概率题都好妙啊 一个精妙的设计是再定义一个状态N 表示当前串不包含任何人的概率 举个例子 来自这里 ...

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

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

  8. 【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)

    [BZOJ4820][SDOI2017]硬币游戏(高斯消元) 题面 BZOJ 洛谷 题解 第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了.然而点数 ...

  9. [Sdoi2017]硬币游戏 [高斯消元 KMP]

    [Sdoi2017]硬币游戏 题意:硬币序列,H T等概率出现,\(n \le 300\)个人猜了一个长为$ m \le 300$的字符串,出现即获胜游戏结束.求每个人获胜概率 考场用了[1444: ...

最新文章

  1. 中国民航大学计算机学院宿舍,中国民航大学计算机科学与技术学院研究生导师简介-谢丽霞_清华大学宿舍...
  2. markdown to html
  3. iOS开发网络篇—GET请求和POST请求
  4. python3-python3--内置函数
  5. 跨域问题解决方案--Nginx代理转发
  6. ubuntu16.04安装Virtualbox
  7. 一加、OPPO官宣合并,“父子团圆”能否拯救一加?
  8. spark 源码分析之八--Spark RPC剖析之TransportContext和TransportClientFactory剖析
  9. Kafka Streams简介: 让流处理变得更简单
  10. 第五章:Redis持久化-AOF持久化
  11. Picasso源码阅读笔记三
  12. 七种实用地方微信推广方法,三个月7000粉丝的秘诀
  13. OPPO推送:推送消息的字串,用于参数
  14. awg线规,直径,面积,电流对照
  15. 期货开户公司想恶意滑点是做不到的
  16. 数据立方体(Data Cube)
  17. 对话系统 NLU项目总结报告
  18. 【教程】在天河上安装、移植并验证CESM2.2.0
  19. 把C盘正好分成100G的数值
  20. 怎么把c盘恢复出厂设置电脑语言,教你把电脑恢复出厂设置

热门文章

  1. stm32F051系列教程 前哨篇 建立一个KEIL工程模板
  2. 准备写一本协议方面的书,谁赞成,谁反对?
  3. 李迟2021年4月知识总结
  4. MFC小笔记:控件随窗口变化
  5. 最优化读书笔记R(二)
  6. 【算法】普里姆算法 Prim算法解决修路问题
  7. 【Elasticsearch】Elasticsearch:Searchable snapshot - 可搜索的快照
  8. es system call filters failed to install; check the logs and fix your configuration or disable syste
  9. 【Kafka】Kafka 0.10.0版本获取Kafka每个分区最新Offset的几种方法
  10. 【MySQL】ERROR 1412 (HY000) Table definition has changed, please retry transaction