[luogu3706]硬币游戏
(可以参考洛谷4548,推导过程较为省略)
定义$g_{i}$表示随机$i$次后未出现给定字符串的概率,$f_{k,i}$表示随机$i$次后恰好出现$s_{k}$(指第$k$个字符串)的概率,设两者的生成函数分别为$G(x)$和$F_{k}(x)$
同样,考虑如何去表示$P(前i个字符中未出现给定字符串且最后m个字符为s_{t})$:
1.通过$g_{i}$,此时即为$\frac{g_{i}}{2^{m}}$;
2.通过$f_{k,i}$(注意虽然最后$m$个字符为$s_{t}$,但可能之前$s_{k}$出现了),枚举第一个出现$s_{k}$的位置$i+j$(右端点),同时必然要有$s_{t}$的前$j$个字符等于$s_{k}$末尾$j$个字符,此时转移的系数为$\frac{1}{2^{m-j}}$
记$S_{t,k}=\{j|s_{t}[0,j)=s_{k}[m-j,m)\}$,两者相等即$\forall 1\le t\le n,\frac{g_{i}}{2^{m}}=\sum_{k=1}^{n}\sum_{j\in S_{t,k}}\frac{f_{k,i+j}}{2^{m-j}}$,写成生成函数的形式即$\forall 1\le t\le n,G(x)=\sum_{k=1}^{n}\sum_{j\in S_{t,k}}\frac{2^{j}F_{k}(x)}{x^{j}}$
关于$S_{i,j}$的计算可以使用AC自动机或哈希,复杂度为$o(n^{2}m)$(虽然AC自动机可以$o(nm)$构建,但枚举$j$还是要$o(n^{2}m)$的)
答案即求$F_{k}(1)$,代入$x=1$后可以得到$n$个等式,但同时新增$G(1)$,再利用$\sum_{k=1}^{n}F_{k}(1)=1$就是恰好$n+1$个等式和变量,高斯消元即可,时间复杂度为$o(n^{3})$
(代码中的写法是以$G(1)$为常数去表示$F_{k}(1)$,再累加求出$G(1)$)
(另外精度问题很是神奇,可能数据中$n$和$m$的并不太大?)

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 305
4 #define eps 1e-10
5 vector<int>v[N];
6 queue<int>q;
7 int V,n,m,nex[N*N],len[N*N],ch[N*N][31];
8 double sum,mi[N],vis[N*N],a[N][N],ans[N];
9 char s[N];
10 void add(int p){
11 int k=1;
12 for(int i=0;i<m;i++){
13 if (!ch[k][(s[i]=='T')]){
14 ch[k][(s[i]=='T')]=++V;
15 len[V]=len[k]+1;
16 }
17 k=ch[k][(s[i]=='T')];
18 v[p].push_back(k);
19 }
20 }
21 void build(){
22 nex[1]=1;
23 for(int i=0;i<2;i++)
24 if (ch[1][i]){
25 nex[ch[1][i]]=1;
26 q.push(ch[1][i]);
27 }
28 while (!q.empty()){
29 int k=q.front();
30 q.pop();
31 for(int i=0;i<2;i++)
32 if (ch[k][i]){
33 int j=nex[k];
34 while ((j>1)&&(!ch[j][i]))j=nex[j];
35 if (ch[j][i])j=ch[j][i];
36 nex[ch[k][i]]=j;
37 q.push(ch[k][i]);
38 }
39 }
40 }
41 void guess(){
42 for(int i=1;i<=n;i++){
43 int t=-1;
44 for(int j=i;j<=n;j++)
45 if (abs(a[i][j])>=eps){
46 t=j;
47 break;
48 }
49 for(int j=i;j<=n;j++)swap(a[i][j],a[t][j]);
50 double s=a[i][i];
51 for(int j=i;j<=n+1;j++)a[i][j]/=s;
52 for(int j=i+1;j<=n;j++){
53 double s=a[j][i];
54 for(int k=i;k<=n+1;k++)a[j][k]-=s*a[i][k];
55 }
56 }
57 for(int i=n;i;i--){
58 ans[i]=a[i][n+1];
59 for(int j=1;j<i;j++){
60 a[j][n+1]-=ans[i]*a[j][i];
61 a[j][i]=0;
62 }
63 }
64 }
65 int main(){
66 scanf("%d%d",&n,&m);
67 V=1;
68 for(int i=1;i<=n;i++){
69 scanf("%s",s);
70 add(i);
71 }
72 build();
73 mi[0]=1;
74 for(int i=1;i<=m;i++)mi[i]=mi[i-1]*2;
75 for(int i=1;i<=n;i++){
76 for(int j=0;j<m;j++)vis[v[i][j]]=mi[j];
77 a[i][n+1]=1;
78 for(int j=1;j<=n;j++)
79 for(int k=v[j].back();k>1;k=nex[k])a[i][j]+=vis[k];
80 for(int j=0;j<m;j++)vis[v[i][j]]=0;
81 }
82 guess();
83 for(int i=1;i<=n;i++)sum+=ans[i];
84 for(int i=1;i<=n;i++)printf("%.6f\n",ans[i]/sum);
85 }
[luogu3706]硬币游戏的更多相关文章
- luogu3706 [SDOI2017]硬币游戏
LINK:硬币游戏 对于40分的暴力 构造出AC自动机 列出转移矩阵 暴力高消.右转上一篇文章. 对于100分 我们不难想到这个矩阵过大 且没有用的节点很多我们最后只要n个节点的答案 其他节点的答案可 ...
- TYVJ P1075 硬币游戏 Label:dp
背景 农民John的牛喜欢玩硬币,所以John就为它们发明了一个新的两人硬币游戏,叫做Xoinc. 描述 最初地面上有一堆n个硬币(5<=n<=2000),从上面数第i个硬币的价值为C_i ...
- tyvj P1075 - 硬币游戏 博弈DP
P1075 - 硬币游戏 From price Normal (OI)总时限:10s 内存限制:128MB 代码长度限制:64KB 背景 Background 农民John的牛喜欢玩 ...
- 1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏
1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右 ...
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...
- BZOJ 1411&&Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】
1411: [ZJOI2009]硬币游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 897 Solved: 394[Submit][Status ...
- [Sdoi2017]硬币游戏 [高斯消元 KMP]
[Sdoi2017]硬币游戏 题意:硬币序列,H T等概率出现,\(n \le 300\)个人猜了一个长为$ m \le 300$的字符串,出现即获胜游戏结束.求每个人获胜概率 考场用了[1444: ...
- 51Nod 1381 硬币游戏
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6445369.html 1381 硬币游戏 基准时间限制:1 秒 空间限制:131072 KB 分值 ...
- 【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)
[BZOJ4820][SDOI2017]硬币游戏(高斯消元) 题面 BZOJ 洛谷 题解 第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了.然而点数 ...
随机推荐
- 密码学系列之:加密货币中的scrypt算法
目录 简介 scrypt算法 scrypt算法详解 scrypt的使用 简介 为了抵御密码破解,科学家们想出了很多种方法,比如对密码进行混淆加盐操作,对密码进行模式变换和组合.但是这些算法逐渐被一些特 ...
- JS 开发中数组常用的方法
大家有没有想过,js数组为什么会有这么多的方法,没错,就是为了不同场景下处理数据的需要,就像设计模式一样,都是为了能更好的处理当前场景的需要. 首先怎么创建一个数组呢, // 两种方式 // 1,构造 ...
- Java初步学习——2021.10.05每日总结,第五周周二
(1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 今天学习了二维数组,包括二维数组的声明,和二维数组的创建.以及获取二维数组的长度,其中要注意的是二维数组是每个元素都是一维数 ...
- Mybatis一级缓存的锅
问题背景 项目开发中有一个树形数据结构,不像经典组织结构树.菜单级别树,我们这个树形结构是用户后期手动建立起来的关系.因此数据库表结构为两张表:数据记录表.记录关系表,通过业务规则限制,形成的树形结构 ...
- Tomcat实现自定义类加载器
什么是类加载器? 这是官方给的定义 在 Java 虚拟机的实现中,初始类可以作为命令行参数提供. 或者,该实现可以提供一个初始类,该类设置一个类加载器,该类加载器依次加载应用程序. 初始类的其他选择也 ...
- Java(33)IO流的介绍&字节流
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228446.html 博客主页:https://www.cnblogs.com/testero ...
- 【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换
总览 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象.所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了.在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光 ...
- BUAA软件工程:软件案例分析
BUAA软件工程:软件案例分析 Author:17373015 乔玺华 项目 内容 这个作业属于哪个课程 2020计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析博客作业 我在这个 ...
- Noip模拟44 2021.8.19
比较惊人的排行榜 更不用说爆零的人数了,为什么联赛会这么难!!害怕了 还要再努力鸭 T1 Emotional Flutter 考场上没切掉的神仙题 考率如何贪心,我们把黑色的条延长$s$,白色的缩短$ ...
- 六个好习惯让你的PCB设计更优(转)
PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...