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

题面

BZOJ

洛谷

题解

第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了。然而点数太多了,三方的消元没法做。

考虑如何优化点数,首先我们的所有点可以分为两种,一种是终止节点,另外一种则不是。

既然现在要某一个串出现,因此我们唯一需要考虑的是到达终止节点的情况。设\(f_i\)表示到达第\(i\)个串的终止位置,并且没有到达过其他终止节点的概率,也就是第\(i\)个串的答案。设\(f_0\)表示没有到达任何一个串终止位置的概率。

那么显然的,要到达当前位置,我们一种可行的方法就是在没有匹配上任何一个串的串后面接上当前串,那么概率就是\(f_0*\frac{1}{2^m}\),然而这个东西显然会比\(f_i\)要大,因为这个终止串再接上当前串可能包含了其他的串\(j\),而\(f_0\)表示的串没有匹配上任何一个串,意味着\(j\)的后缀是\(i\)的前缀。那么考虑所有其他串与当前串前后缀的匹配长度\(k\),我们可以列出方程:

\[f_0*\frac{1}{2^m}=f_i+\sum_j f_j*\frac{1}{2^{m-k}}
\]

而然这样子是\(n+1\)元,\(n\)个方程,再利用\(\sum f_i=1\)补足最后一个方程即可。

好神仙啊。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define ull unsigned long long
#define MAX 320
const ull base=233;
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m;char ch[MAX];
ull h[MAX][MAX],pw[MAX];
ull geths(int x,int l,int r){return h[x][r]-h[x][l-1]*pw[r-l+1];}
double g[MAX][MAX],bin[MAX];
void Guass()
{
for(int i=0;i<=n;++i)
{
int p=i;
for(int j=i+1;j<=n;++j)if(fabs(g[j][i])>fabs(g[p][i]))p=j;
swap(g[p],g[i]);
double t=g[i][i];
for(int j=i;j<=n+1;++j)g[i][j]/=t;
for(int j=i+1;j<=n;++j)
{
double t=g[j][i];
for(int k=0;k<=n+1;++k)g[j][k]-=g[i][k]*t;
}
}
for(int i=n;i;--i)
{
g[i][n+1]/=g[i][i];
for(int j=i-1;j;--j)
g[j][n+1]-=g[i][n+1]*g[j][i];
}
}
int main()
{
n=read();m=read();pw[0]=bin[0]=1;
for(int i=1;i<=m;++i)pw[i]=pw[i-1]*base,bin[i]=bin[i-1]/2;
for(int i=1;i<=n;++i)
{
scanf("%s",ch+1);
for(int j=1;j<=m;++j)h[i][j]=h[i][j-1]*base+ch[j];
}
g[0][n+1]=1;
for(int i=1;i<=n;++i)
{
g[0][i]=1;g[i][0]=-bin[m];
for(int j=1;j<=n;++j)
for(int k=1;k<=m;++k)
if(geths(i,1,k)==geths(j,m-k+1,m))
g[i][j]+=bin[m-k];
}
Guass();
for(int i=1;i<=n;++i)printf("%.10lf\n",g[i][n+1]);
return 0;
}

【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)的更多相关文章

  1. [BZOJ4820][SDOI2017]硬币游戏(高斯消元+KMP)

    比较神的一道题,正解比较难以理解. 首先不难得出一个(nm)^3的算法,对所有串建AC自动机,将在每个点停止的概率作为未知数做高斯消元即可. 可以证明,AC自动机上所有不是模式串终止节点的点可以看成一 ...

  2. [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash)

    [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash) 题面 扔很多次硬币后,用H表示正面朝上,用T表示反面朝上,会得到一个硬币序列.比如HTT表示第一次正面朝上, ...

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

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

  4. BZOJ4820 Sdoi2017 硬币游戏 【概率期望】【高斯消元】【KMP】*

    BZOJ4820 Sdoi2017 硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实 ...

  5. BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)

    容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...

  6. [bzoj4820][Sdoi2017]硬币游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢. 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了 ...

  7. 【bzoj3105】[cqoi2013]新Nim游戏 高斯消元求线性基

    题目描述 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从 ...

  8. BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]

    以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高 ...

  9. BZOJ 2466 中山市选2009 树 高斯消元+暴力

    题目大意:树上拉灯游戏 高斯消元解异或方程组,对于全部的自由元暴力2^n枚举状态,代入计算 这做法真是一点也不优雅... #include <cstdio> #include <cs ...

随机推荐

  1. 【转】Influxdb 编译

    编译针对当前 github上influxdb的master代码 其实github上的CONTRIBUTING.md 里已经说的很明白,按其一步步来开即开,唯一遇到的问题可能就是下载依赖时被墙无法下载, ...

  2. Luogu P1129 [ZJOI2007]矩阵游戏

    题目意思还是比较直观的,而且这个建模的套路也很明显. 我们首先考虑从主对角线可以转移到哪些状态. 由于每一次操作都不会把同一行(列)的黑色方块分开.因此我们发现: 只要找出\(n\)个黑色棋子,让它们 ...

  3. [Oracle]快速生成大量模拟数据的方法

    快速生成大量模拟数据的方法: create table TEST(id integer, TEST_NUMBER NUMBER(18,6)); insert into TEST select i+j, ...

  4. Rancher + k8s + docker 部署资料

    一.k8s 文档: https://jimmysong.io/kubernetes-handbook/concepts/deployment.html 命令行大全 https://kubernetes ...

  5. EF5.0区别于EF4.0的crud区别

    public T AddEntity(T entity) { //EF4.0的写法 添加实体 //db.CreateObjectSet<T>().AddObject(entity); // ...

  6. 运维中的日志切割操作梳理(Logrotate/python/shell脚本实现)

    对于Linux系统安全来说,日志文件是极其重要的工具.不知为何,我发现很多运维同学的服务器上都运行着一些诸如每天切分Nginx日志之类的CRON脚本,大家似乎遗忘了Logrotate,争相发明自己的轮 ...

  7. 《linux内核设计与实现》第三章

    1.进程 进程就是正在执行的程序代码的实时结果,不仅包含可执行代码,还包括其他资源,比如:打开的文件,挂起的信号,内核内部数据结构,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程 ...

  8. Linux内核期中

    Linux内核期中总结 一.计算机是如何工作的 个人理解:计算机就是通过和用户进行交互,执行用户的指令,这些指令存放在内存中,通过寄存器存储,堆栈变化,来一步步顺序执行. 二.存储程序计算机工作模型 ...

  9. ajax多级菜单栏

    1.jsp 首先ajax查询数据 <script type="text/javascript"> function targetlist() { $.ajax({ ur ...

  10. Hibernate_HQL

    public class According_condition { public static void main(String[]args){ Session session=HibernateU ...