码迷,mamicode.com
首页 > 其他好文 > 详细

弱题题解

时间:2017-07-29 10:23:46      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:lin   iostream   一个   std   保留   .com   init   class   ret   

题面:

题目描述

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

输入

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

输出

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

样例输入

2 3 2
3 0

样例输出

1.667
1.333
考试时想到了一个最暴力的dp转移,竟然骗到了55分,数据太水QAQ。。。。。。
递推公式其实很好想,f[i][j]代表到第i个球到第j次的期望个数,但是发现第二维没有办法开,于是滚动数组,用O(n*k)的效率转移
f[i][j]=f[i][j^1]+f[i-1][j^1]/m-f[i][j^1]/m;
    =(m-1)/m*f[i][j^1]+f[i-1][j^1]
技术分享
发现这个玩意其实可以矩阵优化,先构造矩阵,但是又发现如果普通矩阵n^3的效率肯定要T,
其实这个矩阵不管自乘多少次第i行都是由第i-1行右移一位,所以只需要算出第一行在递推转移即可
于是时间为O(n^2*log)
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,k;
 7 double f[1005],a[1005][1005],temp[1005];
 8 void init() {
 9     double p1=(double)(m-1)/m,p2=(double)1/m;
10     for(int i=1; i<=n; i++) {
11         a[i][i]=p1;
12     }
13     for(int i=1; i<n; i++) {
14         a[i][i+1]=p2;
15     }
16     a[n][1]=p2;
17 }
18 int main() {
19     scanf("%d%d%d",&n,&m,&k);
20     for(int i=1; i<=n; i++) {
21         scanf("%lf",&f[i]);
22     }
23     init();
24     for(; k; k>>=1) {
25         if(k&1) {
26             for(int i=1; i<=n; i++) {
27                 temp[i]=0;
28                 for(int j=1; j<=n; j++) {
29                     temp[i]+=f[j]*a[j][i];
30                 }
31             }
32             for(int i=1; i<=n; i++) {
33                 f[i]=temp[i];
34             }
35         }
36         for(int i=1; i<=n; i++) {
37             temp[i]=0;
38             for(int j=1; j<=n; j++) {
39                 temp[i]+=a[1][j]*a[j][i];
40             }
41         }
42         for(int i=1; i<=n; i++) {
43             a[1][i]=temp[i];
44         }
45         for(int i=2; i<=n; i++) {
46             a[i][1]=a[i-1][n];
47             for(int j=2; j<=n; j++) {
48                 a[i][j]=a[i-1][j-1];
49             }
50         }
51     }
52     for(int i=1; i<=n; i++) {
53         printf("%0.3lf\n",f[i]);
54     }
55     return 0;
56 }

 

 

弱题题解

标签:lin   iostream   一个   std   保留   .com   init   class   ret   

原文地址:http://www.cnblogs.com/forevergoodboy/p/7253340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!