@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\).最开 ...
随机推荐
- 笔记二(JavaWeb)
上一个笔记写的好累,这次换Markdown试试 缺省适配器设计模式:父类不实现该方法,让子类去实现(抽象方法) 模板方法设计模式:定义一个操作中的方法骨架,而将一些步骤延迟到子类中.模板方法使得子类可 ...
- Istio-架构
读书笔记整理 工作机制:分为控制面和数据面 控制面:Pilot, Mixer(接收来自Envoy上报的数据), Citadel(证书和密钥管理) 数据面:Envoy 工作流程: 自动注入 应用程序启动 ...
- poi--读取不同类型的excel表格
要想根据不同类型excel表格获取其数据,就要先判断其表格类型 poi-api种方法: getCellType public int getCellType() Return th ...
- 已解决[Authentication failed for token submission,Illegal hexadecimal charcter s at index 1]
在初次学习使用shiro框架的时候碰到了这个问题,具体报错情况如下: [org.apache.shiro.authc.AbstractAuthenticator] - Authentication f ...
- DataFrame的apply用法
DataFrame的apply方法: def cal_value_percent(row,total_value): row['new_column']=row[estimated_value_col ...
- STM32读取匿名光流数据——与Guidance的光流和超声波做对比测试
使用两个串口同时读取匿名光流和Guidance数据:用以比较两个光流的效果 Github链接:https://github.com/W-yt/YuTian_Pro/tree/master/Guidan ...
- 本地安装JDK1.7和1.8,可相互快速切换
1.JDK官网下载jdk1.7和jdk1.8 https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 2.将jdk1.7 ...
- Java实现 LeetCode 513 找树左下角的值
513. 找树左下角的值 给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输 ...
- Java实现 LeetCode 287 寻找重复数
287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...
- Java实现蓝桥杯VIP算法训练 二元函数
试题 算法训练 二元函数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 令二元函数f(x,y)=ax+by,a和b为整数,求一个表达式S的值. 只有满足以下要求的表达式才是合法的: ...