【CF618G】Combining Slimes 概率+矩阵乘法
【CF618G】Combining Slimes
题意:一个长度为$1\times n$的网格,每次从最右侧往里推入一个数字1或2(数字会一直跑到最左边的空格子里),加入1的概率为p,2的概率为1-p。如果新加入的数与其左边的那个数相同,都=x,则将二者合并变成x+1。然后继续判断是否能与左边合并(跟2048差不多)。问你当最后格子满时,整个网格中所有数的和的期望值。
$n\le 10^9$
题解:cf怎么总喜欢利用浮点数精度来出题啊?!(现在遍地都是模意义下的期望mod 998244353,这个性质完全不敢用)
我们设a[i][j]表示用一个长度为i的网格造出一个数字j的概率,显然有$a[i][j]=a[i][j-1]\times a[i-1][j-1]$(j=1,2特殊处理)。以及b[i][j]表示在a的基础之上,要求第一个数字为2的概率,显然$b[i][j]=b[i][j-1]\times a[i-1][j-1]$。
观察一番你会发现,当j增大时a[i][j]急剧减小,当j=50时便可以忽略不计,所以我们就可以只考虑出现1..50的概率了。并且a[..][j]自从不为0开始便保持不变,于是用a[50][..]完全可以代表a[..][..]。
那么如何表示右数第i个格子的数正好为j的概率呢?不难发现它等于$a[i][j]\times(1-a[i-1][j])$。于是令$a'[i][j]=a[i][j]\times(1-a[i-1][j]),b'[i][j]=b[i][j]\times(1-a[i-1][j])$。
然后就可以DP了,用f[i][j]表示第i个格子是j时,右面i个格子总和的期望值。容易得到DP方程:
$j\neq1:f[i][j]=j+{(\sum\limits_{k=1}^{j-1}f[i-1][k]\times a'[i-1][k])\over \sum\limits_{k=1}^{j-1}a'[i-1][k]}$
$j=1:f[i][j]=j+{(\sum\limits_{k=2}^{50}f[i-1][k]\times b'[i-1][k])\over \sum\limits_{k=2}^{50}b'[i-1][k]}$
所以先预处理出前50项,剩余的进行矩阵乘法就好了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef double db;
const int m=50;
struct M
{
db v[60][60];
M () {memset(v,0,sizeof(v));}
db * operator [] (const int &a) {return v[a];}
M operator * (const M &a) const
{
M b;
int i,j,k;
for(i=0;i<=m;i++) for(j=0;j<=m;j++) for(k=0;k<=m;k++) b.v[i][j]+=v[i][k]*a.v[k][j];
return b;
}
}S,T;
db p,a[60][60],b[60][60],f[60][60];
int n;
inline void pm(int y)
{
while(y)
{
if(y&1) S=S*T;
T=T*T,y>>=1;
}
}
int main()
{
int i,j,k,t;
double tmp;
scanf("%d%d",&n,&t),p=t*1e-9;
a[1][1]=p,a[1][2]=1-p;
b[1][2]=1-p;
for(i=2;i<=m;i++)
{
a[i][1]=p,a[i][2]=1-p,b[i][2]=1-p;
for(j=2;j<=m;j++) a[i][j]+=a[i][j-1]*a[i-1][j-1],b[i][j]+=b[i][j-1]*a[i-1][j-1];
}
for(i=m;i>=1;i--) for(j=1;j<=m;j++) a[i][j]*=1-a[i-1][j],b[i][j]*=1-a[i-1][j];
f[1][1]=1,f[1][2]=2;
for(i=2;i<=m;i++)
{
for(j=2;j<=m;j++)
{
tmp=0;
for(k=1;k<j;k++) f[i][j]+=f[i-1][k]*a[i-1][k],tmp+=a[i-1][k];
f[i][j]=f[i][j]/tmp+j;
}
tmp=0;
for(k=2;k<=m;k++) f[i][1]+=f[i-1][k]*b[i-1][k],tmp+=b[i-1][k];
f[i][1]=f[i][1]/tmp+1;
}
if(n<=m)
{
tmp=0;
for(i=1;i<=n+1;i++) tmp+=f[n][i]*a[n][i];
printf("%.12lf",tmp);
return 0;
}
S[0][0]=T[0][0]=1;
for(i=2;i<=m;i++)
{
tmp=0;
for(j=1;j<i;j++) T[j][i]+=a[m][j],tmp+=a[m][j];
for(j=1;j<i;j++) T[j][i]/=tmp;
T[0][i]=i;
}
tmp=0;
for(i=2;i<=m;i++) T[i][1]+=b[m][i],tmp+=b[m][i];
for(i=2;i<=m;i++) T[i][1]/=tmp;
T[0][1]=1;
for(i=1;i<=m;i++) S[0][i]=f[m][i];
pm(n-m);
tmp=0;
for(i=1;i<=m;i++) tmp+=S[0][i]*a[m][i];
printf("%.12lf",tmp);
return 0;
}
【CF618G】Combining Slimes 概率+矩阵乘法的更多相关文章
- BZOJ2553[BeiJing2011]禁忌——AC自动机+概率DP+矩阵乘法
题目描述 Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传 ...
- 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法
题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...
- 【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元
题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两 ...
- BZOJ 1444 [JSOI2009]有趣的游戏 (AC自动机、概率与期望DP、矩阵乘法)
诶这题洛谷居然没有??? 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1444 题解: 我见到主要有三种做法. 一是矩阵乘法.设\(d ...
- hdu4920 Matrix multiplication 模3矩阵乘法
hdu4920 Matrix multiplication Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 ...
- POJ3744Scout YYF I(求概率 + 矩阵快速幂)
Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6757 Accepted: 1960 Descr ...
- HDU 5607 graph(DP+矩阵乘法)
[题目链接] http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=663&pid=1002 [题意] 给定一个有向 ...
- HDU 5607 graph(矩阵乘法)
题意 在一个 \(n\) 个节点 \(m\) 条边的有向图上随机游走,有 \(Q\) 个询问,每次给定一个起点 \(u\) 和步数 \(K\) ,每次回答最后停在每个节点的概率. \(1 \leq n ...
- bzoj2396: 神奇的矩阵(矩阵乘法+随机化)
这题n三方显然会GG... 运用矩阵乘法的性质A*B*R=A*(B*R)=C*R,于是随机化出一个一列的R,就可以把复杂度降低成n方...大概率是不会错的 #include<iostream&g ...
随机推荐
- man 转 pdf _____ jpg 转 pdf
man -t bash | ps2pdf - bash.pdf 将jpeg转成pdf convert *.jpeg images.pdf 将pdf转成jpeg gs -dBATCH -dNOPAUSE ...
- perforce变量配置与使用
linux Perforce 使用 1.配置环境变量: 下载 perforce 放到/usr/bin/下 export P4PORT=192.168.4.88:1666 #P4所在的主机exp ...
- jquery easyui datagrid实现单行的上移下移,以及保存移动的结果
1.实现行的上移.下移. 说明: 1.1 通过datagrid生成的表格有固定的格式,比如,表格div的class名是datagrid-view.比如每一行tr都有id和datagrid-row-in ...
- pyqt与拉勾网爬虫的结合
人力部需要做互联网金融行业的从业人员薪酬分析,起初说的是写脚本,然后他们自己改.但这样不太好,让人事部来修改py脚本不太好,这需要安装py环境和一些第三方包,万一脚本改来改去弄错了,就运行不起来了. ...
- C#------如何深度克隆一个对象
普通版: public static object CloneObject( object obj ) { using ( MemoryStream memStream = new MemoryStr ...
- SpringMVC由浅入深day02_7上传图片
7 上传图片 7.1 需求 在修改商品页面,添加上传商品图片功能. 7.2 springmvc中对多部件类型解析 在页面form中提交enctype="multipart/form-data ...
- 在Linux上安装jdk,mysql,tomcat的准备工作
准备工作: 因为JDK,TOMCAT,MYSQL的安装过程中需要从网上下载部分支持包才可以继续,所以要提前安装下载好下面四个依赖 yum install glibc.i686 yum -y insta ...
- php 安装rabbitmq扩展无报错版
需要安装rabbitmq-c,rabbitmq-c是一个用于C语言的,与AMQP server进行交互的client库.下载了v0.5.2版本(https://github.com/alanxz/ra ...
- Bypass ngx_lua_waf SQL注入防御(多姿势)
0x00 前言 ngx_lua_waf是一款基于ngx_lua的web应用防火墙,使用简单,高性能.轻量级.默认防御规则在wafconf目录中,摘录几条核心的SQL注入防御规则: select.+ ...
- 数组名和数组名取地址&
在C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址. 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是“指向int的常量指针“ ...