solutions

题面(loj)

题面(luogu)

这个题吧是我很久很久以前留下的坑了,到了今天才补好。(是不是太菜了)

暴力

这个和之前的题解一样,确实可以用 trie 树,这复杂度是\(\mathcal{O(n^3m^3)}\)。

您就是初学OI,也不应该看到数据范围之后想到这样的复杂度。

所以这个暴力就直接舍弃吧。

但是如果别的题用到了,还是可以试一试的,毕竟考试的时候部分分还是比较重要的。

正解

不知道咱也不知道为啥这个题的思路可以如此的妙。

首先考虑,每一个合法的能够让一个玩家赢的字符串序列一定是由一个啥也匹配不上的序列和当前玩家的序列构成并且当前玩家的序列是整个序列的后缀。

但是你发现,完全无法找全这样的每一个序列,并且序列是无限个的。

假如我当前有一个序列 S ,那么我可以得到一个合法的序列。

设这个合法的序列为 \(N=S+a_j\),\(a_j\) 为每一个玩家的序列。

可能你会认为,这样不就是 \(j\) 玩家获胜的概率了????

你错了,你不知道这个 \(S\) 里面会发生什么,也许这个 \(S\) 中已经满足了另外一个玩家的序列

所以一切都在不可测之中。

但是你并不关心前面的序列究竟是什么,因为他的末尾一定是 \(a_j\)。

这样的话我们就需要把前面所有的情况都算上,全部!!!

比如说我们这里有两个人 \(HT\) , \(TH\)。

那么我们就有这样一个不太好的序列 \(HTH\) ,这种序列就是我所说的那种坏坏的序列

虽然他是以 \(TH\) 结尾的,但是他前面包含了 \(HT\) 这个序列,所以我们会发现,

在以 \(TH\) 结尾的所有序列中(前面可以加入任意多个字符,当然也可以不加),

我们发现,这种序列的贡献由两部分组成,一部分是 \(TH\) 结尾的贡献,

另一部分就是 \(HT\) 结尾的贡献,那么现在最大的问题就是如何计算这个贡献。

你发现这时候想着想着正解就在眼前了。

这时候你不确定这些序列会造成多少贡献,就是你不知道这些以玩家序列结尾的序列的贡献

所以这里也是一个未知数N,那其他的玩家胜利的概率 \(x_i\) ,这时候我们已经找到了 \(n+1\) 个未知数了。

接下来的任务就是如何求解这些未知数了,一般遇到这么多未知数,一眼就是高斯消元。

所以我们就要寻找这些未知数之间的关系。

第一个方程,一定会有一个玩家胜利,那么 \(\sum\limits_{i=1}^{n}x_i=1\)

根据刚才我们的分析,我们发现,对于以玩家序列结尾的序列可以根据每两个玩家的序列分为很多部分,

这个序列出现的概率就是 \(\frac{1}{n}N\) 而如果当前玩家的前缀和其他玩家的后缀相同,

那这个概率就可以表示为这些玩家胜出的概率再乘上出现当前情况的概率,

我们设 \(fro_{ij}\) 表示 \(i\) 玩家的长度为 \(j\) 的前缀,后缀同样处理为 \(beh_{ij}\)

于是我们就有 \(\frac{1}{n}N=\sum\limits_{i=1}^{n}x_i\sum\limits_{j=1}^{n}\sum\limits_{k=0}^{m}[fro_{ik}==beh_{jk}]\frac{1}{2^{m-k}}\)

这时候我们就有 \(n+1\) 条方程了,就是直接高斯消元即可

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ull unsigned long long
#define double long double
const int N=305;
int n,m;
char ch[N][N];
ull hs[N][N],bas=131,ba[N];
double a[N][N],x[N],mse[N];
signed main(){
scanf("%d%d",&n,&m);
ba[0]=1;mse[0]=1;
for(re i=1;i<=m;i++)
ba[i]=ba[i-1]*bas,
mse[i]=mse[i-1]/2.0;
for(re i=1;i<=n;i++){
scanf("%s",ch[i]+1);
for(re j=1;j<=m;j++)
hs[i][j]=hs[i][j-1]*bas+ch[i][j];
}
for(re i=1;i<=n;i++){
for(re j=1;j<=n;j++){
double ans=0;
for(re k=0;k<=m;k++){
ull tmpf=hs[i][k];
ull tmpb=hs[j][m]-hs[j][m-k]*ba[k];
if(tmpf==tmpb)ans+=mse[m-k];//cout<<k<<" ";
}
//cout<<endl;
//cout<<ans<<" "<<mse[0]<<endl;
a[i][j]=ans;
}
a[i][n+1]=-mse[m];
}
for(re i=1;i<=n;i++)a[n+1][i]=1.0;
a[n+1][n+2]=1.0;n++;
int h,z;
for(h=1,z=1;h<=n&&z<=n;h++,z++){
int maxn;
for(re i=h;i<=n;i++)
if(a[i][z]!=0){
maxn=i;break;
}
if(maxn!=h)
for(re i=1;i<=n+1;i++)
swap(a[maxn][i],a[h][i]);
//if(fabs(a[h][z])==0){
// h--;continue;
//`}
for(re i=h+1;i<=n;i++)
if(a[i][z]!=0){
double t=a[i][z]/a[h][z];
for(re j=z;j<=n+1;j++)
a[i][j]-=a[h][j]*t;
}
}
//cout<<h<<" "<<z<<endl;
for(re i=n;i>=1;i--){
double t=a[i][n+1];
for(re j=n;j>i;j--)
t-=a[i][j]*x[j];//cout<<t<<" "<<a[i][j]<<endl;
x[i]=t/a[i][i];
//cout<<t<<endl;
}
for(re i=1;i<=n-1;i++){
printf("%.10Lf\n",x[i]);
}
}


<题解>[SDOI2017]硬币游戏的更多相关文章

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

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

  2. 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元

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

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

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

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

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

  5. 4820: [Sdoi2017]硬币游戏

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

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

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

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

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

  8. luogu3706 [SDOI2017]硬币游戏

    LINK:硬币游戏 对于40分的暴力 构造出AC自动机 列出转移矩阵 暴力高消.右转上一篇文章. 对于100分 我们不难想到这个矩阵过大 且没有用的节点很多我们最后只要n个节点的答案 其他节点的答案可 ...

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

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

随机推荐

  1. JavaScript 中的 Var,Let 和 Const 有什么区别

    一.var 在ES5中,顶层对象的属性和全局变量是等价的,用var声明的变量既是全局变量,也是顶层变量 注意:顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象 var ...

  2. 【模板】关于vector的lower_bound和upper_bound以及vector基本用法 STL

    关于lower_bound和upper_bound 共同点 函数组成: 一个数组元素的地址(或者数组名来表示这个数组的首地址,用来表示这个数组的开头比较的元素的地址,不一定要是首地址,只是用于比较的& ...

  3. Serverless Web Function 实践教程(一):快速部署 Node.js Web 服务

    作为目前广受欢迎的 Web 服务开发语言,Node.js 提供了众多支持 HTTP 场景的相关功能,可以说是为 Web 构建而生.因此,基于 Node.js,也诞生了多种 Web 服务框架,它们对 N ...

  4. N沟通场效应管深度图解(1)工作原理及Multisim实例仿真

    场效应晶体管(Field Effect Transistor, FET)简称场效应管,是一种由多数载流子参与导电的半导体器件,也称为单极型晶体管,它主要分型场效应管(Junction FET, JFE ...

  5. Vue(4)Vue指令的学习1

    前言 Vue官网一共有提供了14个指令,分别如下 v-text v-html v-show v-if ☆☆☆ v-else ☆☆☆ v-else-if ☆☆☆ v-for ☆☆☆ v-on ☆☆☆ v ...

  6. 【进阶之路】深入理解Java虚拟机的类加载机制(长文)

    我们在参加面试的时候,经常被问到一些关于类加载机制的问题,也都会在面试之前准备的时候背好答案,但是我们是否有去深入了解什么是类加载机制呢?这段时间因为一些事情在家看了些书,这次就和大家分享一些关于Ja ...

  7. Redis之Sentinel

    Redis的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用场景这种故障处理的方式是无法接受的.可喜的是Redis从 2.8 ...

  8. JavaScript模块化的演变

    自执行函数(IIFE): 作用:马上执行这个函数,自执行函数(IIFE),不易读 (function(x){console.log(x);})(3); 易读版本: (function(x){ retu ...

  9. XCTF Guess-the-Number

    一.发现是jar文件,一定想到反汇编gdui这个工具,而且运行不起来,可能是我电脑问题,我就直接反编译出来了. 也发现了flag,和对应的算法,直接拉出来,在本地运行,后得到flag 二.java代码

  10. Apache Superset 1.2.0教程 (二)——快速入门(可视化王者英雄数据)

    上一篇我们已经成功的安装了superset,那么该如何可视化我们的数据呢?本文将可视化王者英雄的数据,快速的入门Superset. 一.连接数据源 首先确保mysql可以正常连接使用,并且准备好数据. ...