考虑生成函数来做

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. python基础3之文件操作、字符编码解码、函数介绍

    内容概要: 一.文件操作 二.字符编码解码 三.函数介绍 一.文件操作 文件操作流程: 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 基本操作: #/usr/bin/env ...

  2. 5213 Exp3 免杀原理与实践

    5213 Exp3 免杀原理与实践 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编程等免杀工具或技巧 使用msf编码器 ...

  3. Vultr搭建SS服务

    购买VPS VPS又叫虚拟服务器,相当于是讲物理服务器的资源进行虚拟划分然后分配给不同的用户使用. Vultr服务器按小时计费,最低0.004美元/h,算起来2.5美元/月,且destory掉服务器是 ...

  4. 汇编  cdecl 函数调用约定,stdcall 函数调用约定

    知识点:  cdecl 函数调用约定  stdcall 函数调用约定  CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...

  5. 微信小程序之分享或转发功能(自定义button样式)

    小程序页面内发起转发 通过给 button 组件设置属性open-type="share",可以在用户点击按钮后触发 Page.onShareAppMessage 事件,如果当前页 ...

  6. servelt filter listener 的生命周期

    1. servlet    当第一次请求一个servlet资源时,servlet容器创建这个servlet实例,并调用他的 init(ServletConfig config)做一些初始化的工作,然后 ...

  7. python list的一个面试题

    面试题''' 一个list,里面的数字偶数在左边,奇数在右边,不借助其他列表 ''' def userlist(add_list): if type(add_list)==list: if len(a ...

  8. 对NP问题的一点感想

    一.概述 回忆欧拉回路问题,要求找出一条经过图的每条边恰好一次的路径,这个问题是线性可解的.哈密尔顿圈问题是找一个简单圈,该圈包括图的每一个顶点.对于这个问题,现在还没有发现线性算法. 对于有向图的单 ...

  9. Js_Eval方法

    定义和用法eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法eval(string) 其中参数string为必需.是要计算的字符串,其中含有要计算的 JavaScr ...

  10. python3面向对象注意事项

    一.面向对象super的作用: class parent(object): def __init__(self): self.test() def test(self): print('parent- ...