题目大意

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

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

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

数据范围

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

思路

第一次见到循环矩阵优化 dp 的套路,记录一下。

转移方程很好得到,设 \(f[i][j]\) 表示到第 \(i\) 轮 \(j\) 编号的球的期望个数,转移方程就是

\[f[i][j]=\cfrac{m-1}{m}\ f[i-1][j]+\cfrac{1}{m}\ f[i-1][j-1]\ (2\leq j\leq n)
\]
\[f[i][1]=\cfrac{m-1}{m}\ f[i-1][1]+\cfrac{1}{m}\ f[i-1][n]
\]

通过 \(K\) 的范围的提示,我们冲一个矩阵快速幂即可,时间效率 \(O(n^3\log K)\)

\(n\leq 1000\)

那没事了。

假设 \(n=4\),我们构造出转移矩阵:

\[ \left[
\begin{matrix}
f[i-1][1] & f[i-1][2] & f[i-1][3] & f[i-1][4]
\end{matrix}
\right]
\times
\left[
\begin{matrix}
\cfrac{m-1}{m} & \cfrac{1}{m} & 0 & 0 \\
0 & \cfrac{m-1}{m} & \cfrac{1}{m} & 0 \\
0 & 0 & \cfrac{m-1}{m} & \cfrac{1}{m} \\
\cfrac{1}{m} & 0 & 0 & \cfrac{m-1}{m}
\end{matrix}
\right]
=
\left[
\begin{matrix}
f[i][1] & f[i][2] & f[i][3] & f[i][4]
\end{matrix}
\right]
\]

我们发现转移矩阵是一个循环矩阵。

那么这个矩阵满足什么性质呢?

我们设第一排的第 \(i\) 个数为 \(k[i]\),我们以 \(k[1]\) 为例:

\[k[1]=a[1][1]\times a[1][1]+a[1][2]\times a[2][1]+a[1][3]\times a[3][1]+a[1][4]\times a[4][1]
\]

我们将其对应到第一行的元素,得到:

\[k[1]=k[1]\times k[1]+k[2]\times k[4]+k[3]\times k[3]+k[4]\times k[2]
\]

很容易看出性质:

\[k[t]=\sum\limits_{((i+j-2)\ \text{mod}\ n)+1=t}k[i]\times k[j]
\]

所以我们只需要记录第一行的状态,用 \(O(n^2\log K)\)转移即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
int n,m,K; struct Mat{
double a[maxn];
Mat(){
memset(a,0,sizeof(a));
}
friend inline Mat operator *(register const Mat& A,register const Mat& B){
Mat C;
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++)
C.a[(i+j-2)%n+1]+=A.a[i]*B.a[j];
return C;
}
}ans,base; inline int read(){
int x=0;bool fopt=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fopt=0;
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-48;
return fopt?x:-x;
} inline void qpow(int b){
while(b){
if(b&1)ans=ans*base;
base=base*base;
b>>=1;
}
} int main(){
n=read();m=read();K=read();
for(int i=1;i<=n;i++)
ans.a[i]=read();
base.a[1]=1.0*(m-1)/m;
base.a[2]=1.0/m;
qpow(K);
for(int i=1;i<=n;i++)
printf("%.3lf\n",ans.a[i]);
return 0;
}

【循环矩阵乘优化DP】BZOJ 2510 弱题的更多相关文章

  1. bzoj 2510: 弱题 循环矩阵

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

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

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

  3. [BZOJ 2510]弱题

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

  4. bzoj 2510: 弱题 概率期望dp+循环矩阵

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

  5. bzoj 2510 弱题 矩阵乘

    看题就像矩阵乘 但是1000的数据无从下手 打表发现每一行的数都是一样的,只不过是错位的,好像叫什么循环矩阵 于是都可以转化为一行的,O(n3)->O(n2)*logk #include< ...

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

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

  7. CodeForces621E 快速矩阵幂优化dp

    有时些候在用快速矩阵幂优化dp的时候,它的矩阵乘法是不那么容易被具体为题目背景的意思的,大多数时候难以理解矩阵之间相乘的实际意义,正如有时候我们不知道现在在做手头这些事情的意义,但倘若是因一个目标而去 ...

  8. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  9. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

随机推荐

  1. Java中枚举的用法

    public enum Week { DAY1("周一", 0.9), DAY2("周二", 0.9), DAY3("周三", 0.8), ...

  2. 起redis服务时报错Creating Server TCP listening socket *:6379: bind: No such file or directory

  3. 生成token和获取token

    1.先安装模块pip install itsdangerous 举个例子:一个用户登录成功后,讲username和token作为key,value写到redis里面,判断是否失效(1.时间到了失效,2 ...

  4. 踩坑了,JDK8中HashMap依然会死循环!

    是否你听说过JDK8之后HashMap已经解决的扩容死循环的问题,虽然HashMap依然说线程不安全,但是不会造成服务器load飙升的问题. 然而事实并非如此.少年可曾了解一种红黑树成环的场景,=v= ...

  5. c语言之结构

    定义结构: struct point { int x; int y; }; 定义结构并声明变量: struct point { int x; int y; }pt1,pt2,pt3; 声明结构变量 s ...

  6. NX二次开发-使用NXOPEN C#手工搭建开发环境配置

    新建类库 进来后编译代码,成功 添加NXOPEN的库到项目中 不同NX版本,可能dll所在位置不一样,NX11以上版本在NXBIN这里,NX11以下版本大概在UGII. 添加头文件 using NXO ...

  7. 提效工具-python解析xmind文件及xmind用例统计

    现状 每个公司都有一个维护测试case的系统,有自研的也有买的,比如QC, 禅道等等,QA往往习惯使用xmind等思维导图工具来编写测试用例,因为思路清晰,编写方便,那么这就有一个问题,大多公司要求所 ...

  8. BurpSuite抓取本地包方法

    本文重点在介绍抓本地包, 而非介绍抓包步骤 Burpsuite配置 默认配置即可 Chrome 浏览器配置 Falcon Proxy扩展程序配置浏览器代理. 需要抓包的网页是个本地搭建的网址, 一般会 ...

  9. Apache shiro权限基本使用

    l shiro框架的核心功能:认证.授权.会话管理.加密 Application Code:应用程序代码,由开发人员负责开发的 Subject:框架提供的接口,代表当前用户对象 SecurityMan ...

  10. python基础-面向对象opp

    上述是实例化对象的一个过程. 类的定义和实例化: class Role(object): #定义一个类, class是定义类的语法,Role是类名,(object)是新式类的写法,必须这样写,以后再讲 ...