[SDOI2017]硬币游戏

时间:2023-02-02 16:03:36

[SDOI2017]硬币游戏

考虑生成函数来做

[SDOI2017]硬币游戏

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. BZOJ&colon;4820&colon; &lbrack;Sdoi2017&rsqb;硬币游戏&amp&semi;&amp&semi;BZOJ&colon;1444&colon; &lbrack;Jsoi2009&rsqb;有趣的游戏(高斯消元求概率)

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

  2. &lbrack;Sdoi2017&rsqb;硬币游戏 &lbrack;高斯消元 KMP&rsqb;

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

  3. 【BZOJ4820】&lbrack;SDOI2017&rsqb;硬币游戏(高斯消元)

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

  4. 4820&colon; &lbrack;Sdoi2017&rsqb;硬币游戏

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

  5. BZOJ4820 Sdoi2017 硬币游戏 【概率期望】【高斯消元】【KMP】&ast;

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

  6. 【BZOJ4820】&lbrack;Sdoi2017&rsqb;硬币游戏 AC自动机&plus;概率DP&plus;高斯消元

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

  7. &lbrack;BZOJ 4820&rsqb; &lbrack;SDOI2017&rsqb; 硬币游戏&lpar;高斯消元&plus;概率论&plus;字符串hash&rpar;

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

  8. luogu3706 &lbrack;SDOI2017&rsqb;硬币游戏

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

  9. &lbrack;bzoj4820&rsqb;&lbrack;Sdoi2017&rsqb;硬币游戏

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

  10. BZOJ 4820 &lbrack;SDOI2017&rsqb; 硬币游戏

    Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了.同学们觉得要加强趣味性,所以要找 ...

随机推荐

  1. Apache服务器安装过程及问题的解决&lpar;for windows system32bit&rpar;

    在使用Hbuilder设计网站时,在制作本站搜索时,用到了Php文件,而Hbuilder的内置web服务器不支持php的解析, 所以需要安装配置外部服务器,有多个选择,我安装的apache服务器,并遇 ...

  2. Linux下运行memcached失败

    Linux下运行memcached失败 1.错误信息如下 [root@localhost ~]# memcached can't run as root without the -u switch 2 ...

  3. arcgis手动启动服务提示端口4000被使用

    具体解决办法 参考 http://hi.baidu.com/xjx19860908/item/6b46376d92044694c4d249f6该博文. 手动启动,提示4000端口被占用,去查找4000 ...

  4. 细数Android开源项目中那些频繁使用的并发库中的类

    这篇blog旨在帮助大家 梳理一下前面分析的那些开源代码中喜欢使用的一些类,这对我们真正理解这些项目是有极大好处的,以后遇到类似问题 我们就可以自己模仿他们也写 出类似的代码. 1.ExecutorS ...

  5. NOI2002银河英雄传说

    原先就看过这道题,觉得很复杂. 不知道为什么今天一看觉得好水啊…… 难道这就是并查集的启发式合并? 数组d[i]表示i到其父节点的距离,即中间隔了多少船舰. 数组sum[i]记录以i为根的集合总共有多 ...

  6. Hadoop 2&period;6&period;3运行自带WordCount程序笔记

    运行平台:Hadoop 2.6.3 模式:完全分布模式 1.准备统计文本,以一段文字为例:eg.txt The Project Gutenberg EBook of War and Peace, by ...

  7. Python日志模块logging&amp&semi;JSON

    日志模块的用法 json部分 先开一段测试代码:注意  str可以直接处理字典   eval可以直接将字符串转成字典的形式 dic={'key1':'value1','key2':'value2'} ...

  8. uvm&lowbar;pre&lowbar;do

    https://blog.csdn.net/tingtang13/article/details/46535649 1.uvm_do 封装了一系列接口,封装越多,灵活性越差.所以增加了三个接口:pre ...

  9. 【转载】jdk1&period;8 LongAdder源码学习

    本文转自https://blog.csdn.net/u011392897/article/details/60480108 LongAdder是jdk8新增的用于并发环境的计数器,目的是为了在高并发情 ...

  10. Dockerfile 构建kibana 反向代理应用做用户认证访问

    FROM centos MAINTAINER z*****ch.cn RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &amp ...