[BZOJ4204] 取球游戏(期望)
[题目描述]
有\(m\)个球,一开始每个球均有一个初始标号,标号范围为\(1~n\)且为整数,标号为\(i\)的球有\(a_{i}\)个,并保证\(Σa_{i} = m\)。
每次操作等概率取出一个球(即取出每个球的概率均为\(\frac{1}{m}\)),若这个球标号为\(k(k < n)\),则将它重新标号为\(k + 1\);若这个球标号为\(n\),则将其重标号为\(1\)。(取出球后并不将其丢弃)
现在你需要求出,经过\(K\)次这样的操作后,每个标号的球的期望个数。
\(dp[i]:\)编号为\(i\)的球的个数
\(dp[i]=dp[i]+dp[i−1]∗\frac{1}{m}−dp[i]∗\frac{1}{m}\)
\(dp[i]=\frac{1}{m}dp[i-1]+\frac{m-1}{m}dp[i]\)
写成矩阵形式,发现是个循环矩阵(从第2行开始都是由前一行向右移一位得到的)
循环矩阵乘循环矩阵还是循环矩阵
所以只要记录第一行即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
}
const int MAXN=1005;
int dp[MAXN];
int n,m,k;
struct Matrix{
int N;
double a[MAXN];
friend Matrix operator * (Matrix a,Matrix b){
Matrix res;
res.N=a.N;
/*memset(res.a,0,sizeof res.a);
for(int i=1;i<=a.N;i++)
for(int j=1;j<=b.N;j++)
for(int i=1;i<=a.N;i++)
res.a[i][j]+=a.a[i][k]*b.a[k][j];*/
for(int i=1;i<=res.N;i++){
res.a[i]=0;
for(int j=1;j<=res.N;j++)
res.a[i]+=a.a[j]*b.a[(i-j+res.N)%res.N+1];
}
return res;
}
};
inline Matrix qpow(Matrix a,int b){
Matrix res;
res.N=a.N;
memset(res.a,0,sizeof res.a);
res.a[1]=1;
while(b){
if(b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
int main(){
// freopen("asd.in","r",stdin);
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++) dp[i]=read();
if(n==1){
printf("%d.000\n",dp[1]);
return 0;
}
Matrix t;
t.N=n;
memset(t.a,0,sizeof t.a);
t.a[1]=(double)(m-1)/m;
t.a[2]=(double)1.0/m;
t=qpow(t,k);
assert(t.N==n);
for(int i=1;i<=n;i++){
double ans=0;
for(int j=1;j<=n;j++)
ans+=(double)dp[j]*t.a[(i-j+t.N)%t.N+1];
printf("%.3lf\n",ans);
}
}
[BZOJ4204] 取球游戏(期望)的更多相关文章
- bzoj4204: 取球游戏
好神啊.. 首先递推随便yy一下就行了 然后发现可以用矩阵优化,不过显然是n^3logk的,不资磁 于是就有了性质,这个转移矩阵显然是一个循环矩阵(并不知道) 循环矩阵乘循环矩阵还是循环矩阵 然后就可 ...
- nyist 518 取球游戏
http://acm.nyist.net/JudgeOnline/problem.php?pid=518 取球游戏 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 今 ...
- 取球游戏|2012年蓝桥杯B组题解析第十题-fishers
(25')取球游戏 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出 ...
- 取球游戏_nyoj_518(博弈-蓝桥杯原题).java
取球游戏 时间限制: 1000 ms | 内存限制: 65535 KB 难度: 2 描述 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下 ...
- nyoj_518_取球游戏_201404161738
取球游戏 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个 ...
- 蓝桥杯 第三届C/C++预赛真题(10) 取球游戏(博弈)
今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球的数目必须是:1 ...
- hihoCoder offer 收割练习赛 74B 取球游戏
Observations 存在取球策略使得每个四连通块可以只剩一个球:保证取走一个球后仍然是个四连通块. 定义新的[相邻]关系:两球在同一行中且所在行中二者之间无其他球,或者两球在同一列且所在列中二者 ...
- java实现取球游戏
/* 今盒子里有 n 个小球,A.B 两人轮流从盒中取球,每个人都可以看到另一个人取了多少个, 也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球的 ...
- 2016蓝桥杯"取球博弈"问题
较难,网上有能得出正确结果的代码,但是读了一下,像是拼凑出的结果,逻辑不通,代码和注释不符 参考网上代码写了一版,结构相对清晰,注释比较详细 题目很长: 两个人玩取球的游戏.一共有N个球,每人轮流取球 ...
随机推荐
- 详解python包管理器pip安装
pip对于使用python的朋友并不陌生,当你想安装python模块的时候一定会首先想到它.pip 是一个安装和管理 Python 包的工具 , 是 easy_install 的一个替换品. 今天来说 ...
- Linux网络配置之虚拟网卡的配置(ubuntu 16.04)
关于图形界面的配置,我这里就不多介绍了,这个很简单.这里介绍的是如何通过修改配置文件来实现虚拟网卡. 首先介绍ubuntu(我这里使用的是ubuntu-16.04)下虚拟网卡的配置 1.先用ifcon ...
- javascript总结31 :DOM概述
1 JavaScript 三个组成部分 核心(ECMAScript)欧洲计算机制造商协会 描述了JS的语法和基本对象. 文档对象模型(DOM) 处理网页内容的方法和接口 浏览器对象模型(BOM) 与浏 ...
- javascript总结26:Date
1 获取Date对象 Date-引用类型,JavaScript中的内置对象 获取当前时间 var date = new Date(); //UTC的时间 //返回数字,时间的毫秒形式 var date ...
- CodeForces 408E Curious Array(组合数学+差分)
You've got an array consisting of n integers: a[1], a[2], ..., a[n]. Moreover, there are m queries, ...
- Verilog MIPS32 CPU(二)-- Regfiles
Verilog MIPS32 CPU(一)-- PC寄存器 Verilog MIPS32 CPU(二)-- Regfiles Verilog MIPS32 CPU(三)-- ALU Verilog M ...
- Fiddler2抓包
https://www.cnblogs.com/conquerorren/p/8472054.html https://www.cnblogs.com/conquerorren/p/8472218.h ...
- C#反射的基本应用
反射描述了在运行过程中检查和处理程序元素的功能.反射可以完成以下任务: 枚举类型的成员: 实例化新对象: 执行对象的成员: 查找类型的信息: 查询程序集的信息: 检查应用于某种类型的自定义特性: 创建 ...
- Java 访问修饰符使用规则
作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × × 1. ...
- Ubuntu16.04以root身份登入!
首先以非root用户身份登入系统. 1,修改root密码:启动shell,随后在shell里面输入命令: sudo passwd root 最后输入root要使用的密码,需要输入两次,这样root密码 ...