我是靠谱客的博主 典雅鞋垫,最近开发中收集的这篇文章主要介绍循环矩阵的快速幂(bzoj 2510: 弱题),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

2510: 弱题

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 408   Solved: 218
[ Submit][ Status][ Discuss]

Description

M个球,一开始每个球均有一个初始标号,标号范围为1~N且为整数,标号为i的球有ai个,并保证Σai = M
每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为kk < N),则将它重新标号为k + 1;若这个球标号为N,则将其重标号为1。(取出球后并不将其丢弃)
现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数。

Input

第1行包含三个正整数NMK,表示了标号与球的个数以及操作次数。
第2行包含N非负整数ai,表示初始标号为i的球有ai个。

Output

应包含N行,第i行为标号为i的球的期望个数,四舍五入保留3位小数。

Sample Input

2 3 2
3 0

Sample Output

1.667
1.333


题名可以。。

先考虑概率dp:dp[x][y]表示第x个回合后,标号为y的小球的期望个个数,那么有


直接转移的话,复杂度是O(nk)的,肯定会超时,不过还好这个递推式显然能转化成矩阵

假设n只有4,那么有递推


矩阵快速幂的话复杂度就降为(n^3logk)了,但n有1000那么大,还是超时。。。

但仔细看这个矩阵可以发现一个特点:它的每一行都是上一行往右移动一位得到的

不但如此,这个矩阵无论自乘多少次,都满足这个性质,所以理论上只需要维护第一行就好了

那么怎么得出新的矩阵第一行?

令k[i]表示矩阵第一行的第i个,那么有


同理


很显然可以看出规律


这样复杂度就是(n²log(k))了


#include<stdio.h>
#include<string.h>
int n;
double ans[1005], Jz[1005], temp[1005];
void Mult(double *a, double *b)
{
int i, j;
memset(temp, 0, sizeof(temp));
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
temp[(i+j-2)%n+1] += a[i]*b[j];
}
memcpy(a, temp, sizeof(temp));
}
int main(void)
{
int m, k, i;
while(scanf("%d%d%d", &n, &m, &k)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%lf", &ans[i]);
Jz[1] = 1-1.0/m;
Jz[2] = 1.0/m;
while(k)
{
if(k%2==1)
Mult(ans, Jz);
Mult(Jz, Jz);
k /= 2;
}
for(i=1;i<=n;i++)
printf("%.3fn", ans[i]);
}
return 0;
}



最后

以上就是典雅鞋垫为你收集整理的循环矩阵的快速幂(bzoj 2510: 弱题)的全部内容,希望文章能够帮你解决循环矩阵的快速幂(bzoj 2510: 弱题)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部