题目大意

  有\(M\)个球,一开始每个球均有一个初始标号,标号范围为\(1-N\)且为整数,标号为i的球有\(a_i\)个,并保证\(\sum a_i=M\)。

  每次操作等概率取出一个球(即取出每个球的概率均为\(1/M\)),若这个球标号为\(k(k < N)\),则将它重新标号为\(k + 1\);若这个球标号为\(N\),则将其重标号为\(1\)。(取出球后并不将其丢弃)

  现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数。

\(N ≤ 1000, M ≤ 100,000,000, K ≤ 2,147,483,647\)

题目分析

递推方程很好想,但是需要优化。

由于\(K\)很大,考虑使用矩阵乘法优化\(dp\)。但是\(n\)的范围太大,不能直接化出矩阵来相乘。通过观察矩阵,我们很容易发现矩阵的每一行之间是循环的,因此,我们可以只算一行即可,矩阵相乘的时间负责度瞬间降低为\(O(n^2)\),矩阵快速幂优化后总时间复杂为\(O(n^2log_2 n)\)

#include <bits/stdc++.h>
using namespace std;
int n,m,k;
namespace Task1{
double p[2][1005];
void solve(){
for(int i=1;i<=n;i++)scanf("%lf",&p[0][i]);
int cur=0,pre;
for(int i=1;i<=k;i++){
pre=cur;cur^=1;
for(int j=1;j<=n;j++){
if(j==1)p[cur][j]=p[pre][j]+p[pre][n]/m-p[pre][j]/m;
else if(j==n)p[cur][j]=p[pre][j]+p[pre][j-1]/m-p[pre][j]/m;
else p[cur][j]=p[pre][j]+p[pre][j-1]/m-p[pre][j]/m;
}
}
for(int i=1;i<=n;i++)cout<<fixed<<setprecision(3)<<p[cur][i]<<"\n";
}
}
namespace Task2{
double tmp[1005][1005];
struct node{
double a[1005];
node(){memset(a,0,sizeof(a));}
double&operator[](int x){return a[x];}
node operator*(node &b){
node c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int pos=i+j-1;
if(pos>n)pos-=n;
tmp[j][pos]=b[i];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
c[i]+=a[j]*tmp[j][i];
return c;
}
node operator^(int cnt){
node ret,mul=*this;
bool flag=0;
for(;cnt;cnt>>=1,mul=mul*mul)if(cnt&1){if(!flag)ret=mul,flag=1;else ret=ret*mul;}
return ret;
}
}p;
void solve(){
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
node mul;
mul[1]=(m-1)/double(m);
mul[2]=1.0/m;
mul=mul^k;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int pos=i+j-1;
if(pos>n)pos-=n;
tmp[j][pos]=mul[i];
}
node ans;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans[i]+=p[j]*tmp[j][i];
for(int i=1;i<=n;i++)printf("%.3lf\n",ans[i]);
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
if(1ll*n*k<=5e7)Task1::solve();
else Task2::solve();
}
/*
[(m-1)/m,1/m,0,0,0]
[0,(m-1)/m,1/m,0,0]
[0,0,(m-1)/m,1/m,0]
[0,0,0,(m-1)/m,1/m]
[1/m,0,0,0,(m-1)/m] [a1,a2,a3] [a1,a2,a3] [a1*a1+a2*a3+a3*a2,a1*a2+a2*a1+a3*a3,a1*a3+a2*a2+a3*a1]
[a3,a1,a2]*[a3,a1,a2]=[a3*a1+a1*a3+a2*a2,......
[a2,a3,a1] [a2,a3,a1] [...... [a1,a2,a3] [b1,b2,b3] [a1*b1+a2*b3+a3*b2,a1*b2+a2*b1+a3*b3,a1*b3+a2*b2+a3*b1]
[a3,a1,a2]*[b3,b1,b2]=[a3*b1+a1*b3+a2*b2,......
[a2,a3,a1] [b2,b3,b1] [...... [a1,a2,a3]*[b1,b2,b3]=>[a1*b1+a2*b3+a3*b2,a1*b2+a2*b1+a3*b3,a1*b3+a2*b2+a3*b1]
*/

【BZOJ2510】弱题的更多相关文章

  1. Bzoj2510 弱题(矩阵快速幂)

    题面(权限题) 题解 一道概率\(dp\),可以设\(f[i][j]\)表示第\(i\)次操作后,标号为\(j\)的小球的期望个数,那么有: \[ \begin{aligned} &f[i][ ...

  2. BZOJ2510: 弱题

    求k时刻一个标号转移到各位置的概率,最后枚举每个标号加权求期望.可以发现转移矩阵是循环矩阵,因此乘法是n^2的.另外这个乘法是圆周卷积的形式,然后就作死写了发fft,发现精度升天了= = #inclu ...

  3. 2018.09.27 bzoj2510: 弱题(概率dp+循环矩阵优化)

    传送门 简单概率dp. 显然每次转移的式子可以用一个矩阵表示出来: 这个是循环矩阵. 因此只用维护第一行快速幂一波就行了. 代码: #include<bits/stdc++.h> #def ...

  4. [bzoj2510]弱题 (循环矩阵优化dp)

    Description 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个 ...

  5. 【BZOJ2510】弱题 期望DP+循环矩阵乘法

    [BZOJ2510]弱题 Description 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球 ...

  6. 「BZOJ2510」弱题

    「BZOJ2510」弱题 这题的dp式子应该挺好写的,我是不会告诉你我开始写错了的,设f[i][j]为操作前i次,取到j小球的期望个数(第一维这么大显然不可做),那么 f[i][j]=f[i-1][j ...

  7. bzoj 2510: 弱题 循环矩阵

    2510: 弱题 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 124  Solved: 61[Submit][Status][Discuss] De ...

  8. BZOJ 2510: 弱题( 矩阵快速幂 )

    每进行一次, 编号为x的数对x, 和(x+1)%N都有贡献 用矩阵快速幂, O(N3logK). 注意到是循环矩阵, 可以把矩阵乘法的复杂度降到O(N2). 所以总复杂度就是O(N2logK) --- ...

  9. [BZOJ 2510]弱题

    2510: 弱题 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 419  Solved: 226[Submit][Status][Discuss] D ...

  10. 【BZOJ 2510】 2510: 弱题 (矩阵乘法、循环矩阵的矩阵乘法)

    2510: 弱题 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 374  Solved: 196 Description 有M个球,一开始每个球均有一 ...

随机推荐

  1. Docker容器日志查看与清理(亲测有效)

    https://blog.csdn.net/yjk13703623757/article/details/80283729 1. 问题 docker容器日志导致主机磁盘空间满了.docker logs ...

  2. TT 安装之 Windwos

    WINDOWS在 控制面板-〉管理工具-〉本地安全策略-〉本地策略-〉用户权限分配-〉锁定内存页-〉添加用户或组-〉高级查找 然后确定 然后安装 (WINDOWS在 控制面板-〉管理工具-〉ODBC工 ...

  3. C#中Using里使用单例的问题

    又给自己挖了一个坑跳进去. KafkaManager使用单例模型获取到一个producer,然而自己代码里用的时候加了一个using using (var producer = KafkaManage ...

  4. oracle 查看一个表中的记录是否被锁住

    SELECT a.object_id, a.session_id, b.object_nameFROM v$locked_object a, dba_objects bWHERE a.object_i ...

  5. pipline --学习 (-)

    一,语法: 编写位置: pipline 启动docker pipeline { agent { docker 'maven:3.3.3' } stages { stage('build') { ste ...

  6. Python Fileinput 模块

    作者博文地址:http://www.cnblogs.com/liu-shuai/ fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行. [默 ...

  7. 《HTTP权威指南》之HTTP连接管理及对TCP性能的考虑

    在上一篇博客中(<HTTP权威指南>之HTTP相关概念详解)我们简单对HTTP相关的基本概念做了一些简单的了解,但未对HTTP连接管理的内容做一些详细的介绍.本篇博客我们就一起来看一下HT ...

  8. poi excel 常用api

    http://www.cnblogs.com/huajiezh/p/5467821.html

  9. pat02-线性结构3. 求前缀表达式的值(25)

    02-线性结构3. 求前缀表达式的值(25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 算术表达式有前缀表示法.中缀表示法和后缀表示法 ...

  10. LaTex 2

    LaTex 入门 此时是否安装成功 如果安装成功了LaTeX, 那么在计算机上会多出来LaTeX的编译器, LaTex Live 安装包在计算机上安装了多个不同的编译器, 有latex, xelate ...