[bzoj4820][Sdoi2017]硬币游戏
来自FallDream的博客,未经允许,请勿转载,谢谢。
n,m<=300
只会(nm)^3的做法....正解太神啦。
令N表示什么都没匹配到的状态,然后我计算在后面接上一个串的概率
注意到N是什么其实是不确定的,也就是可能还没全部接上去就接好了
更详细地,假设A=HTT,B=TTH
那么p(N+A)=p(A)+p(B)*2^(-1)+p(B)*2^(-2)
p(N+A)=p(N)*2^(-3)
也就是说,有一个串的后缀是我的前缀的时候,它会影响我的概率。
求这种情况可以用kmp
这样就列出了n个方程,在加上一个概率和等于1的方程,就能得到n+1个变量n+1个方程 高斯消元即可。
复杂度n^3
#include<iostream>
#include<cstdio>
#define MN 300
#define ld long double
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int n,m,fail[MN+][MN+];
char st[MN+][MN+];
ld a[MN+][MN+],p[MN+],ans[MN+]; void BuildFail(char*s,int*f)
{
for(int i=,j=;i<=m;++i)
{
while(j&&s[j+]!=s[i]) j=f[j];
if(s[j+]==s[i])++j;f[i]=j;
}
} ld Calc(int y,int x)
{
ld ans=;int j=;
for(int i=;i<=m;++i)
{
while(j&&st[y][j+]!=st[x][i]) j=fail[y][j];
if(st[y][j+]==st[x][i]) ++j;
}
for(;j;) ans+=p[m-j],j=fail[y][j];
return ans;
} void Gauss()
{
for(int i=;i<=n+;++i)
{
for(int j=i;j<=n+;++j)
if(a[j][i])
{
if(j!=i)
for(int k=i;k<=n+;++k)
swap(a[j][k],a[i][k]);
break;
}
for(int j=i+;j<=n+;++j)
{
ld delta=a[j][i]/a[i][i];
for(int k=i;k<=n+;++k)
a[j][k]=a[j][k]-a[i][k]*delta;
}
}
for(int i=n+;i;--i)
{
for(int j=i+;j<=n+;++j)
a[i][n+]-=a[i][j]*ans[j];
ans[i]=a[i][n+]/a[i][i];
}
} int main()
{
n=read();m=read();p[]=;
for(int i=;i<=m;++i) p[i]=p[i-]/;
for(int i=;i<=n;++i)
scanf("%s",st[i]+),a[i][n+]=-p[m];
for(int i=;i<=n;++i) a[n+][i]=;a[n+][n+]=;
for(int i=;i<=n;++i) BuildFail(st[i],fail[i]);
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
a[i][j]=Calc(i,j);
Gauss();
for(int i=;i<=n;++i) printf("%.10lf\n",(double)ans[i]);
return ;
}
[bzoj4820][Sdoi2017]硬币游戏的更多相关文章
- BZOJ4820 Sdoi2017 硬币游戏 【概率期望】【高斯消元】【KMP】*
BZOJ4820 Sdoi2017 硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实 ...
- [BZOJ4820][SDOI2017]硬币游戏(高斯消元+KMP)
比较神的一道题,正解比较难以理解. 首先不难得出一个(nm)^3的算法,对所有串建AC自动机,将在每个点停止的概率作为未知数做高斯消元即可. 可以证明,AC自动机上所有不是模式串终止节点的点可以看成一 ...
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- 【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)
[BZOJ4820][SDOI2017]硬币游戏(高斯消元) 题面 BZOJ 洛谷 题解 第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了.然而点数 ...
- 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元
[BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬 ...
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...
- [Sdoi2017]硬币游戏 [高斯消元 KMP]
[Sdoi2017]硬币游戏 题意:硬币序列,H T等概率出现,\(n \le 300\)个人猜了一个长为$ m \le 300$的字符串,出现即获胜游戏结束.求每个人获胜概率 考场用了[1444: ...
- 4820: [Sdoi2017]硬币游戏
4820: [Sdoi2017]硬币游戏 链接 分析: 期望dp+高斯消元. 首先可以建出AC自动机,Xi表示经过节点i的期望次数,然后高斯消元,这样点的个数太多,复杂度太大.但是AC自动机上末尾节点 ...
- [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash)
[BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash) 题面 扔很多次硬币后,用H表示正面朝上,用T表示反面朝上,会得到一个硬币序列.比如HTT表示第一次正面朝上, ...
随机推荐
- Markdown文本测试
一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 1. 这是一 2. 这是二 这是无序符号 My Github 这是着重表示 这是斜体 一级粗体 二级斜体 cin >> a; c ...
- Struts2之Struts2的下载与安装
Struts2的下载 登陆struts的官网 下载Full Distribution这个选项的struts2的包. 这是Struts2的完整版,里面包括Struts2的实例应用,空实例应用,核心库,源 ...
- shell中冒号 : 用途说明
我们知道,在Linux系统中,冒号(:)常用来做路径的分隔符(PATH),数据字段的分隔符(/etc/passwd)等.其实,冒号(:)在Bash中也是一个内建命令,它啥也不做,是个空命令.只起到占一 ...
- JQuery 动态加载iframe.
html: <iframe id="ifm" style="width:inherit;height:inherit" runat="serve ...
- http客户端请求及服务端详解
http客户端请求及服务端详解 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...
- Pandas速查手册中文版
本文翻译自文章: Pandas Cheat Sheet - Python for Data Science ,同时添加了部分注解. 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非 ...
- LeetCode & Q28-Implement strStr-Easy
String Two Pointers Description: Implement strStr(). Returns the index of the first occurrence of ne ...
- HTML-----<a>、<table>、<form>解析
超链接 anchor 锚 <a href="url">内容</a> Href Hypertext reference 引用 URL(Uniform Re ...
- round()函数 浮点数的四舍五入
浮点数的四舍五入 print round(1.7333) 2.0
- JavaScript push() 方法
定义和用法: push() :可向数组的末尾添加一个或多个元素,并返回新的长度. 语法 arrayObject.push(newelement1,newelement2,....,newelement ...