考虑生成函数来做

g(x)函数就是0+0*x+...+1*x^s+...+|∑|^(n-s)x^n

就是最后s位必须填这个串,但是前面随便填的方案数

然后枚举之前出现了哪个串(包括自己),如果没有相交,就是fj(x)*g(x),还有就是有前后缀有相交部分,

Pji(x)中的第k位,表示i的长度为m-k的前缀和j的长度为m-k的后缀是不是一样 0/1。

再加上最后一个

$\sum f_i=1$因为游戏最终会停止

现在有n+1个方程,g(x)直接当做未知数的话会有交叉项解不出来

把$(1-|\Sigma|x)$乘过去,求导来搞搞事情:

由于带入$x=1/|\Sigma|$使得这个$(1-|\Sigma|x)$等于0,求导可以消去一些项

$-|\Sigma|fi=S(x)^{S-1}-Sx^{S-1}(\sum_jf_j)-x^S(\sum_jf'_j)+|\Sigma|(\sum_jf_jP_{ji})$

把$(\sum_jf'_j)$当做另外一个未知量

就有n+1个未知量,n+1个方程了

根据“洛必达法则”(一种极限处理)由于最后是收敛的,一定有极限,所以带入​当x=1/|∑|的时候不会除以0成为很大的数(我在口胡)

代码:
卡精度,不用eps反而更好

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define ld long double
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=;
const double eps=1e-;
const ll mod[]={,};
const ll jin[]={,};
ll pw[N][];
ll has[N][N][];
char s[N];
ld f[N][N];
ld ans[N];
int n,m;
ld m0,m1;
bool cmp(ld x){
return ;
}
void Guass(int n){
for(reg i=;i<=n;++i){
int id=;
for(reg j=i;j<=n;++j){
if(cmp(f[j][i])&&fabs(f[j][i])>fabs(f[id][i])) id=j;
}
if(id!=i){
for(reg j=;j<=n+;++j){
swap(f[i][j],f[id][j]);
}
}
for(reg j=i+;j<=n;++j){
if(cmp(f[j][i])){
ld tmp=f[j][i]/f[i][i];
for(reg k=;k<=n+;++k){
f[j][k]=f[j][k]-f[i][k]*tmp;
}
}
}
}
for(reg i=n;i>=;--i){
for(reg j=;j<=n;++j){
if(cmp(ans[j])) f[i][n+]-=ans[j]*f[i][j];
}
ans[i]=f[i][n+]/f[i][i];
}
}
int main(){
rd(n);rd(m);
pw[][]=pw[][]=;
for(reg i=;i<=m;++i){
for(reg j=;j<=;++j){
pw[i][j]=pw[i-][j]*jin[j]%mod[j];
}
}
for(reg i=;i<=n;++i){
scanf("%s",s+); for(reg j=;j<=m;++j){
for(reg l=;l<=;++l){
has[i][j][l]=(has[i][j-][l]*jin[l]+s[j]-'A')%mod[l];
}
}
}
m0=m1=1.0;
for(reg i=;i<=m;++i) m1=m1*0.5;
m0=m1*; for(reg i=;i<=n;++i){
// cout<<" turns "<<i<<" ----------------------- "<<endl;
for(reg j=;j<=n;++j){ // cout<<" with "<<j<<endl;
ld tmp=0.5;
ld val=;
for(reg k=;k<=m-;++k){
int to=m-k;
ll bac0=(has[j][m][]-has[j][m-to][]*pw[to][]%mod[]+mod[])%mod[];
ll bac1=(has[j][m][]-has[j][m-to][]*pw[to][]%mod[]+mod[])%mod[]; if(bac0==has[i][to][]&&bac1==has[i][to][]){
// cout<<" ok "<<to<<endl;
val+=tmp;
}
tmp*=0.5;
}
// cout<<" val "<<val<<endl;
f[i][j]=m*m0-2.0*val;
}
f[i][i]-=2.0;
f[i][n+]=m1;
f[i][n+]=m*m0;
} for(reg i=;i<=n;++i){
f[n+][i]=1.0;
}
f[n+][n+]=1.0; // for(reg i=1;i<=n+1;++i){
// for(reg j=1;j<=n+2;++j){
// cout<<f[i][j]<<" ";
// }cout<<endl;
// }
Guass(n+); for(reg i=;i<=n;++i){
printf("%.10Lf\n",ans[i]);
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/2/18 17:41:21
*/

总结:

对于连续一些位置有值的时候,
生成函数确实很好用

求导由于可以降次,这里就把交叉项成功分开了。

PS:这个题也有直接上概率的做法,本质和生成函数相同。但是解释起来最好的绝对是生成函数

[SDOI2017]硬币游戏的更多相关文章

  1. <题解>[SDOI2017]硬币游戏

    solutions 题面(loj) 题面(luogu) 这个题吧是我很久很久以前留下的坑了,到了今天才补好.(是不是太菜了) 暴力 这个和之前的题解一样,确实可以用 trie 树,这复杂度是\(\ma ...

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

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

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

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

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

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

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

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

  6. 4820: [Sdoi2017]硬币游戏

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

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

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

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

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

  9. luogu3706 [SDOI2017]硬币游戏

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

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

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

随机推荐

  1. 20155306 白皎 免考实践总结——0day漏洞

    本次免考实践提纲及链接 第一部分 基础知识 1.1 0day漏洞概述 1.2二进制文件概述 1.3 必备工具 1.4 crack实验 第二部分 漏洞利用 2.1栈溢出利用 2.1.1 系统栈工作原理 ...

  2. Redis学习之路(三)之Redis主从和哨兵模式

    目录 一.Redis主从配置 1.环境说明 2.修改主从的redis配置文件 3.启动主从redis 3.数据同步验证 二.Redis哨兵模式 1.Redis sentinel介绍 2.Redis S ...

  3. 阿里云OSS不同账号之间的迁移

    目录 一.需求说明 二.Ossimport概述 三.配置运行环境 1.配置jdk环境 2.部署方式 3.下载并部署ossimport 四.修改单机Job的配置文件local_job.cfg 五.执行迁 ...

  4. R绘图 第四篇:绘制箱图(ggplot2)

    箱线图通过绘制观测数据的五数总括,即最小值.下四分位数.中位数.上四分位数以及最大值,描述了变量值的分布情况.箱线图能够显示出离群点(outlier),离群点也叫做异常值,通过箱线图能够很容易识别出数 ...

  5. 物理机通过http访问eNSP虚拟Server

    由于测试需要,本文主要通过一个简单的例子介绍通过物理机的浏览器访问华为eNSP虚拟Server,访问网页. 1.首先配置虚拟网卡的地址 2.通过华为的eNSP模拟软件,做出如下拓扑结构图,配置地址如图 ...

  6. LintCode——合并排序数组II

    描述:合并两个排序的整数数组A和B变成一个新的数组 样例:给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 1.Python:先将数组B加到数组A之后,然后 ...

  7. Harbor 学习分享系列1 - centos7.4安装harbor1.5.2

    centos7.4安装harbor1.5.2 前言 本系列分享将Harbor有关教程:分享形式会以百度云盘的形式进行分享,主要教程将以markdown格式进行分享:建议使用markdownpad2这款 ...

  8. 高可用Kubernetes集群-15. 部署Kubernetes集群统一日志管理

    参考文档: Github:https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsear ...

  9. djbc

    jdbc:mysql://localhost:3306:test这句里面分如下解析:jdbc:mysql:// 是指JDBC连接方式:localhost: 是指你的本机地址:3306 SQL数据库的端 ...

  10. 软件工程之四则运算--Github

    由于现在配置问题,然后借用同学电脑将代码上传至Github,网址为:https://github.com/be821/RealFour 参考相关Github文档: 1. http://my.oschi ...