题目:https://www.luogu.org/problemnew/show/P3706

题解:https://blog.csdn.net/gjghfd/article/details/80355976

令 \( p_x \) 表示哪个串都没在结尾匹配上的概率,那么在 \( p_x \) 的基础上再出现 m 个特定的字符就能拼出任意一个串了。

但是在再出现 m 个字符的过程中可能已经匹配上了某个串,比如 HTT 和 THT ,想在 \( p_x \) 的基础上出现 THT 拼出第二个串,但如果是 \( p_x \) 里长成 HT 样子的串的话,再出现一个 T 就会以第一个串为结尾结束了。

每个字符出现的概率是一样的。所以可以认为 \( p_x \) 里出现形如 HT 或者 ***HT ( ***HT 没有匹配上一个串) 之类的串的概率是 \( ( \frac{1}{2} )^2 \) 。不过不太知道为什么是这样。

所以就有 \( p_x*\frac{1}{2^m} = p_i+\sum\limits_{j=1}^{n}p_j\sum\limits_{l \in L_{i,j}}\frac{1}{2^{m-l}} \) ,其中 \( L_{i,j} \) 表示 i 的前缀与 j 的后缀可以匹配的长度的集合。

还有一个式子就是 \( \sum\limits_{i=1}^{n}p_i = 1 \) ,就能高斯消元了。

可以用哈希求 \( L_{i,j} \) 。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define db long double
using namespace std;
const int N=,b1=1e9+,b2=,m1=1e9+,m2=;
int n,m,pw[N][];
bool b[N][N]; db bin[N],a[N][N];
struct Node{
int v0,v1;
Node(int a=,int b=):v0(a),v1(b) {}
bool operator== (const Node &b)const
{return v0==b.v0&&v1==b.v1;}
}h[N][N];
Node get_h(int i,int j)
{
int r0=(h[i][m].v0-(ll)h[i][j-].v0*pw[m-j+][])%m1;
int r1=(h[i][m].v1-(ll)h[i][j-].v1*pw[m-j+][])%m2;
if(r0<)r0+=m1; if(r1<)r1+=m2;
return Node(r0,r1);
}
void solve()
{
pw[][]=pw[][]=;
for(int i=;i<=m;i++)
{
pw[i][]=(ll)pw[i-][]*b1%m1;
pw[i][]=(ll)pw[i-][]*b2%m2;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
h[i][j].v0=((ll)h[i][j-].v0*b1+b[i][j])%m1;
h[i][j].v1=((ll)h[i][j-].v1*b2+b[i][j])%m2;
}
for(int i=;i<=n;i++)a[i][]=-bin[m];//a[][0]:px
a[][n+]=;for(int i=;i<=n;i++)a[][i]=;//a[0][]:sum=1
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
for(int k=;k<=m;k++)
if(h[i][k]==get_h(j,m-k+)) a[i][j]+=bin[m-k];
}
void gauss()
{
for(int i=;i<=n;i++)
{
int bh=i;
for(int j=i+;j<=n;j++)
if(fabs(a[j][i])>fabs(a[bh][i]))bh=j;
for(int j=i;j<=n+;j++)swap(a[i][j],a[bh][j]);
db sl=a[i][i];
for(int j=i;j<=n+;j++)a[i][j]/=sl;//
for(int j=;j<=n;j++)
if(j!=i&&fabs(a[j][i]))
{
sl=a[j][i];
for(int k=i;k<=n+;k++)a[j][k]-=sl*a[i][k];
}
}
}
int main()
{
scanf("%d%d",&n,&m); char ch[N];
bin[]=;for(int i=;i<=m;i++)bin[i]=bin[i-]/;
for(int i=;i<=n;i++)
{
scanf("%s",ch+);
for(int j=;j<=m;j++)b[i][j]=(ch[j]=='H');
}
solve(); gauss();
for(int i=;i<=n;i++)
printf("%.10Lf\n",a[i][n+]);
return ;
}

洛谷 3706 [SDOI2017]硬币游戏——思路的更多相关文章

  1. 洛谷P3706 [SDOI2017]硬币游戏(概率生成函数+高斯消元)

    题面 传送门 题解 不知道概率生成函数是什么的可以看看这篇文章,题解也在里面了 //minamoto #include<bits/stdc++.h> #define R register ...

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

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

  3. 洛咕 P3706 [SDOI2017]硬币游戏

    假设f[i]是第i个同学胜利的概率,也就是随机序列第一个匹配到s[i]的概率 假设前面有一个字符串\(S\),(假设无限长但没有匹配),现在往后面要加上第i个串\(s[i]\),这个的概率设为\(P_ ...

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

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

  5. 洛谷P1118 数字三角形游戏

    洛谷1118 数字三角形游戏 题目描述 有这么一个游戏: 写出一个1-N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直 ...

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

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

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

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

  8. 洛谷P1274-魔术数字游戏

    Problem 洛谷P1274-魔术数字游戏 Accept: 118    Submit: 243Time Limit: 1000 mSec    Memory Limit : 128MB Probl ...

  9. 4820: [Sdoi2017]硬币游戏

    4820: [Sdoi2017]硬币游戏 链接 分析: 期望dp+高斯消元. 首先可以建出AC自动机,Xi表示经过节点i的期望次数,然后高斯消元,这样点的个数太多,复杂度太大.但是AC自动机上末尾节点 ...

随机推荐

  1. SQL Server数据库入门学习总结

    数据库基本是由表,关系,操作组成:对于初学者,首先要学的是: 1.数据库是如何存储数据的 —— 表.约束.触发器 2.数据库是如何操作数据的 —— insert,update,delete.T-sql ...

  2. Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level

    2018-03-23 18:32:21,690 [INFO] [http-nio-11007-exec-2] org.apache.coyote.http11.Http11Processor [Dir ...

  3. 正向代理到指定泛域名的nginx配置

    resolver 8.8.8.8; #必须配置!!!不然无法代理 server { listen default_server; listen [::]: default_server; server ...

  4. 浅谈musql中using的使用---高性能(三)

    转载地址:https://blog.csdn.net/lppl010_/article/details/79429657 mysql中using的用法为: using()用于两张表的join查询,要求 ...

  5. java并发编程:线程安全管理类--原子操作类--AtomicStampedReference<V>

    1.类 AtomicStampedReference<V> AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新. 实现注意事项.通过创 ...

  6. BZOJ1461 字符串的匹配

    什么字符串...明明是两个数列... 分类上来讲,还是一道很好的noip题...(雾) 首先,kmp会不会?(答:会!) 其次,树状数组求顺序对会不会?(再答:会!) 讲完了!>.< 进入 ...

  7. js打开、关闭页面和运行代码那些事

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  8. js框架封装简单实例

    (function(){ window["event"] = {} //event注册到window上面 function init(data){ // 定义一个init内部函数 ...

  9. 深入理解java异常【绝对经典,推荐最少看五遍】

    http://blog.csdn.net/hguisu/article/details/6155636 补充:检查异常(checkedException)与运行异常,什么时候throw,什么时候thr ...

  10. 2017广东工业大学程序设计竞赛决赛 Problem E: 倒水(Water) (详解)

    倒水(Water) Description 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水 ...