luogu3706 [SDOI2017]硬币游戏
LINK:硬币游戏
对于40分的暴力 构造出AC自动机 列出转移矩阵 暴力高消。右转上一篇文章。
对于100分 我们不难想到这个矩阵过大 且没有用的节点很多我们最后只要n个节点的答案 其他节点的答案可以不要。
考虑把没用的节点的答案压到一点上。相同的套路 我们设f[i]表示经过第i个点的期望次数 由于是到达某个点我们强制停止 所以概率*结果=期望次数。
此时结果为1/0 所以这个期望次数在数值之上和概率是相等的。
对于第i个终止节点来说我们考虑一下这个点的期望次数怎么求出。
显然是由非终止节点转移过来 由于每次翻硬币只有两种可能 或者说字符集大小为2 所以转移过来至少需要m条边且 概率为\(\frac{1}{2^m}\)
但是这其中存在一些不合法的情况 如 我们从一个非法状态转移+自身前缀状态的一部分 可能恰好和其他字符串是相等的 此时游戏结束概率也转移不来。
要把这些情况造成的影响全部减掉 \(f_i=\frac{1}{2^m}f_0-...\)上面的事情发生在当前字符串的前缀和其他字符串的后缀相等时会发生。
考虑匹配的长度为k 那个点为j 那么我们要减去 \(\frac{1}{2^{m-k}}f_j\) 所代表的含义为 前m-k长度的那个点的期望次数为 f_j的期望次数的一部分
于是乎就可以列出n个方程 但是有n+1个未知数 考虑加一个方程 \(\sum{f_i}=1\)
写到这里我想就很明朗了 很不错的题目。
这里使用hash判断前后缀 注意初始化的问题 我们对于f[i]的单项系数也在判断前后缀中搞。这样比较方便不需要特判最后一位什么的。
而且最后一位也不合法不属于0号节点里面 所以可以这样做 我迷了半天。。
const int MAXN=310;
int n,m;
char b[MAXN][MAXN];
db a[MAXN][MAXN],p[MAXN];
ll pw[MAXN],qz[MAXN][MAXN],hz[MAXN][MAXN];
inline void GAUSS()
{
for(int i=0;i<=n;++i)
{
int p=i;
for(int j=i+1;j<=n;++j)if(fabs(a[j][i])>fabs(a[p][i]))p=j;
if(i!=p)rep(0,n+1,j)swap(a[i][j],a[p][j]);
rep(0,n,j)
{
if(i==j)continue;
db d=a[j][i]/a[i][i];
rep(0,n+1,k)a[j][k]-=a[i][k]*d;
}
}
rep(0,n,i)a[i][n+1]/=a[i][i];
}
int main()
{
freopen("1.in","r",stdin);
gt(n);gt(m);p[0]=pw[0]=1;
rep(1,n,i)scanf("%s",b[i]+1);
rep(1,m,i)p[i]=p[i-1]/2,pw[i]=pw[i-1]*P%mod;
rep(1,n,i)rep(1,m,j)
{
qz[i][j]=(qz[i][j-1]*P+b[i][j])%mod;
hz[i][j]=(hz[i][j-1]+b[i][m-j+1]*pw[j-1])%mod;
}
rep(1,n,i)
{
a[i][0]+=p[m];
rep(1,n,j)rep(1,m,k)
if(qz[i][k]==hz[j][k])a[i][j]=a[i][j]-p[m-k];
}
rep(1,n+1,i)a[0][i]=1;
//rep(0,n,i){rep(0,n+1,j)cout<<a[i][j]<<' ';cout<<endl;}
GAUSS();
rep(1,n,i)printf("%.10lf\n",a[i][n+1]);
return 0;
}
update:写完后2h又发现了点其他东西 想了半天 发现上述等式没有错。
等式阐述了一个类似于容斥的东西。其中 对于特定的某个点 我们想要走到\(2^{m-k}\)需要这个概率 而右边虽然是 \(2^m\)的系数 但是其代表了后来是走到了fj的
而我们的前者则是 固定为fj 所以这两个东西显然相等。
又思考了20min 想到了一个更合理的思路。还是关于式子的问题。
我们考虑 减掉不合法方案 设不合法方案的点 为w 我们其实多加了一个 \(f_w\frac{1}{2^m}\) 在左边减掉其。
首先我们要先走到w这个点 设此匹配长度为k 那么概率为\(\frac{1}{2^{m-k}}\) 其期望要再乘上fj。
感觉证明还是很不顺畅 先咕了。
luogu3706 [SDOI2017]硬币游戏的更多相关文章
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...
- [Sdoi2017]硬币游戏 [高斯消元 KMP]
[Sdoi2017]硬币游戏 题意:硬币序列,H T等概率出现,\(n \le 300\)个人猜了一个长为$ m \le 300$的字符串,出现即获胜游戏结束.求每个人获胜概率 考场用了[1444: ...
- 【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)
[BZOJ4820][SDOI2017]硬币游戏(高斯消元) 题面 BZOJ 洛谷 题解 第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了.然而点数 ...
- 4820: [Sdoi2017]硬币游戏
4820: [Sdoi2017]硬币游戏 链接 分析: 期望dp+高斯消元. 首先可以建出AC自动机,Xi表示经过节点i的期望次数,然后高斯消元,这样点的个数太多,复杂度太大.但是AC自动机上末尾节点 ...
- BZOJ4820 Sdoi2017 硬币游戏 【概率期望】【高斯消元】【KMP】*
BZOJ4820 Sdoi2017 硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实 ...
- 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元
[BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬 ...
- [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash)
[BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash) 题面 扔很多次硬币后,用H表示正面朝上,用T表示反面朝上,会得到一个硬币序列.比如HTT表示第一次正面朝上, ...
- [bzoj4820][Sdoi2017]硬币游戏
来自FallDream的博客,未经允许,请勿转载,谢谢. 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了 ...
- BZOJ 4820 [SDOI2017] 硬币游戏
Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了.同学们觉得要加强趣味性,所以要找 ...
随机推荐
- (二)ansible 使用
一,ansible 命令格式 #ansible <pattern> -m <module_name> -a <arguments> #单个服务器 ansible 3 ...
- 线性动归之Wooden Sticks
题面:现在有n(n<5000)个木头,每个木头都有长度l和重量w(l<10000,w<10000),现在你要对木头进行加工: 1.第一根木头需要先花费1min: 2.加工完第i跟木头 ...
- 不用加减乘除做加法(剑指offer-48)
题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 题目解析 首先看十进制是如何做的: 5+7=12,三步走 第一步:相加各位的值,不算进位,得到2. 第二步:计 ...
- Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归
Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 目录 Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 内容纲要 1.函数名的第一类对象及使用 2.f ...
- MVC + EFCore 项目实战 - 数仓管理系统4 – 需求分解
上次课程我们完成了项目基本的UI风格配置. 现在就开始进入我们的需求开发,我们先捋一下需求. 一.总体需求说明 项目背景第一篇文章已有介绍,我们回顾一下. 这是一个数据管理"工具类" ...
- Ethical Hacking - GAINING ACCESS(15)
CLIENT SIDE ATTACKS Social Engineering Gather info about the user(s). Build a strategy based on the ...
- vue配置 less 全局变量
在使用Vue开发的过程中,通常会用到一些样式的全局变量,如果在每个组件中引入就太繁琐了,维护性也不好,因此全局引入是个不错的想法.下面以less为例,记录一下全局引入less变量的步骤: 1.首先安装 ...
- 服务端socket重用属性设置
初始化socket socket是一种系统资源,并不是每次初始化都一定成功,因此为了避免初始化失败,一般使用多次初始化的方式,如下所示: unsigned int times = 0x0; while ...
- xmake从入门到精通12:通过自定义脚本实现更灵活地配置
xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文主要详细讲解下,如何通过添加自定义的脚本,在脚 ...
- Java中的大数值使用
在Java中,偶尔会遇到超大数值,超出了已有的int,double,float等等你已知的整数.浮点数范围,那么可以使用java.math包中的两个类:BigInteger和BigDecimal. 这 ...