@loj - 2004@ 「SDOI2017」硬币游戏
@description@
周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利。
大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了。
同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况。
用 H 表示正面朝上, 用 T 表示反面朝上,扔很多次硬币后,会得到一个硬币序列。比如 HTT 表示第一次正面朝上,后两次反面朝上。
但扔到什么时候停止呢?大家提议,选出 n 个同学,每个同学猜一个长度为 m 的序列,当某一个同学猜的序列在硬币序列中出现时,就不再扔硬币了,并且这个同学胜利。为了保证只有一个同学胜利,同学们猜的 n 个序列两两不同。
很快, n 个同学猜好序列,然后进入了紧张而又刺激的扔硬币环节。你想知道,如果硬币正反面朝上的概率相同,每个同学胜利的概率是多少。
@solution@
考虑构造概率生成函数。记 \(f_{i,j}\) 表示第 j 次抛硬币后第 i 名同学恰好获胜的概率,可以构造生成函数 \(F_i(x) = \sum_{p=0}f_{i, p}x^p\)。
再记辅助生成函数 \(g_{i}\) 表示第 i 次抛硬币后仍未结束的概率,构造生成函数 \(G(x) = \sum_{p=0}g_px^p\)。
最后需要求解的每个人的获胜概率 \(P_i = F_i(1) = \sum_{p=0}f_{i, p}\)。
有如下关系式存在:
\]
意思是在一个未结束的序列后加一个字符,要么仍然未结束,要么某一个人获胜。
\]
意识是在一个未结束的序列后加上字符串 \(S_i\),那么一定会结束。
但有可能提前结束,如果结束时 j 胜利,则存在关系 \(S_j[m-k...m-1] = S_i[0...k-1]\),且反过来也是成立。
好像看不出来什么规律。不过注意到我们只需要求 \(F_i(1)\),所以可以直接代 \(x = 1\):
\sum_{j=1}^{n}\sum_{k=1}^{m}[S_j[m-k...m-1] = S_i[0...k-1]]\times (\frac{1}{2})^{m - k}F_j(1) = G(1)\times(\frac{1}{2})^m
\]
这也是概率生成函数的一个好处。
至于剩下的,我们可以 kmp 求出满足 \(S_j[m-k...m-1] = S_i[0...k-1]\) 的所有 k。然后高斯消元即可。
以上这些全部抄自《浅谈生成函数在掷骰子问题上的应用》。
总之像这一类问题应该算是套路吧。。。也说不清楚怎么来的。
@accepted code@
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 300;
double M[MAXN + 5][MAXN + 5];
void gauss(int n, int m) {
int r = 0, c = 0;
while( r < n && c < m ) {
int mxr = r;
for(int i=r+1;i<n;i++)
if( fabs(M[i][c]) >= fabs(M[mxr][c]) )
mxr = i;
if( mxr != r ) {
for(int j=c;j<m;j++)
swap(M[r][j], M[mxr][j]);
}
if( M[r][c] ) {
double k = M[r][c];
for(int j=c;j<m;j++)
M[r][j] /= k;
for(int i=0;i<n;i++) {
if( i == r ) continue;
k = M[i][c];
for(int j=c;j<m;j++)
M[i][j] -= k*M[r][j];
}
r++;
}
c++;
}
}
char s[MAXN + 5][MAXN + 5]; int n, m;
char t[2*MAXN + 5]; int f[2*MAXN + 5];
void get() {
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
for(int k=0;k<m;k++)
t[k] = s[i][k];
t[m] = '#';
for(int k=0;k<m;k++)
t[k+m+1] = s[j][k];
f[0] = -1, f[1] = 0;
for(int k=2;k<=2*m+1;k++) {
f[k] = f[k-1];
while( f[k] != -1 && t[f[k]] != t[k-1] )
f[k] = f[f[k]];
f[k]++;
}
int p = f[2*m + 1];
while( p ) {
M[i][j] += pow(2, -(m-p));
p = f[p];
}
}
// M[i][n] = -pow(2, -m);
M[i][n] = -1;
}
for(int i=0;i<n;i++)
M[n][i] = 1;
M[n][n+1] = 1;
}
int main() {
scanf("%d%d", &n, &m);
for(int i=0;i<n;i++) scanf("%s", s[i]);
get(), gauss(n + 1, n + 2);
for(int i=0;i<n;i++)
printf("%.10f\n", M[i][n+1]);
}
@details@
感觉莫名眼熟?一翻发现有一个 “[jsoi2009]有趣的游戏” 的题目,发现是自己记错了。。。
我原本以为概率生成函数 PGF 和其他的什么 EGF, OGF 差不多,后来发现和我以前做过的生成函数题还是有点区别。
最大的区别可能是 EGF 或 OGF 重要的是函数的系数,而 PGF 可能需要求函数(或者导函数)在 x = 1 上的值。
话说本题计算 2^(-300) 左右的数量级居然没什么精度误差。
@loj - 2004@ 「SDOI2017」硬币游戏的更多相关文章
- 【LOJ 2004】「SDOI2017」硬币游戏
LOJ 2004 100pts 首先我们肯定要建AC自动机的.. 那么这题就肯定是个AC自动机上\(dp\). 所以想想状态. 首先如果我们把状态设成这样行不行: \(dp(i)\)表示匹配到了i节点 ...
- 题解 「SDOI2017」硬币游戏
题目传送门 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利. 大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了. 同学们觉得要加强 ...
- 「SDOI2017」硬币游戏
题目链接 问题分析 首先一个显然的做法就是建出AC自动机,然后高斯消元.但是这样的复杂度是\(O(n^3m^3)\)的. 我们发现其实只需要求AC自动机上\(n\)个状态的概率,而其余的概率是没有用的 ...
- 【LOJ】#2067. 「SDOI2016」硬币游戏
题解 c一样的就是一个独立的游戏 我们对于2和3的指数 sg[i][j] 表示\(c \cdot 2^i \cdot 3^j\)的棋子,只有这个硬币是反面,翻转的硬币是正面的sg值 枚举sg函数所有可 ...
- loj#2269. 「SDOI2017」切树游戏
还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...
- loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)
题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...
- LOJ #2005. 「SDOI2017」相关分析 线段树维护回归直线方程
题目描述 \(Frank\) 对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. \(Frank\) 不仅喜欢观测,还喜欢分析观测到的 ...
- LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)
题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
随机推荐
- IO字节流与字符流的操作
字节流: FileInputStream读取,FileOutputStream输出 字节流使用数组缓冲区复制文件,最后得出所使用的时间 public class work2 { publ ...
- python - 怎样使用 requests 模块发送http请求
最近在学python自动化,怎样用python发起一个http请求呢? 通过了解 request 模块可以帮助我们发起http请求 步骤: 1.首先import 下 request 模块 2.然后看请 ...
- nodejs模块介绍与使用
1.内置模块 http fs path url os等等 (无需安装直接require引入即可) 2.第三方模块: express mysql ejs等等 (npm包管理工具下载require引入) ...
- [Axure教程]0005.系统函数与变量介绍
1.变量的种类: [1].全局变量:可以在整个原型的任意位置调用和修改. [2].局部变量:仅作用于某一事件的某一动作内. [3].自定义变量:自行新建的全局变量. 2.Axure函数: [1].特殊 ...
- GitHub+jsDelivr+PicGo 打造稳定快速、高效免费图床
标题: GitHub+jsDelivr+PicGo 打造稳定快速.高效免费图床 作者: 梦幻之心星 347369787@QQ.com 标签: [GitHub, 图床] 目录: 图床 日期: 2019- ...
- Js 事件表格
- 怎样实现登录?| Cookie or JWT
先问小伙伴们一个问题,登录难吗?"登录有什么难得?输入用户名和密码,后台检索出来,校验一下不就行了."凡是这样回答的小伙伴,你明显就是产品思维,登录看似简单,用户名和密码,后台校验 ...
- Rocket - debug - Example: Accessing Registers Using Program Buffer
https://mp.weixin.qq.com/s/8yYLVg-RXX3XX0T431lxeA 介绍riscv debug接口的使用实例:使用Program Buffer读取寄存器. 1. Wri ...
- Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
hive运行查询语句时报错: Error: org.apache.hive.service.cli.HiveSQLException: Error while processing statement ...
- Java实现 LeetCode 面试题 01.07. 旋转矩阵(按照xy轴转+翻转)
面试题 01.07. 旋转矩阵 给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节.请你设计一种算法,将图像旋转 90 度. 不占用额外内存空间能否做到? 示例 1: 给定 mat ...