弱题

(ps:考试时明明知道是快速幂,但就是构造不出a[][],哎,急死我了)

solution:

暴力:

定义f[i][j]为取i次时j号球期望个数
f[i][j]=f[i-1][j]-f[i-1][j]/m+f[i-1][j-1]/m
f[i][j]=(m-1)/m*f[i-1][j]+1/m*f[i-1][j-1]
内存问题可以用滚动数组

时间复杂度就呵呵了 O(n*k)

稍微正解一点的正解;

定义f[i]为当前第i号球的期望个数

构造矩阵a[][]
以n=4为例
a[4][4]=
(m-1)/m     1/m     0       0
   0     (m-1)/m   1/m      0
   0         0   (m-1)/m   1/m
  1/m        0      0    (m-1)/m
然后矩阵快速幂 O(n^3*logk)

正解:

f[i]一样

我们发现a[][]不管自乘多少次,第i行永远相当于第i-1行往右挪一位  (ps:出题人,您真是太强了)

大家命名曰 循环矩阵

这样 时间复杂度降为O(n^2*logk)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<ctime>
 4 #include<queue>
 5 #include<algorithm>
 6 #include<iostream>
 7 #define dd double
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 using namespace std;
10 
11 int n,m,k;
12 dd f[1001],temp[1001];
13 dd a[1001][1001],b[1001][1001];
14 
15 void out11()
16 {
17     printf("f=\n");
18     for(int i=1;i<=n;++i)
19       printf("%.3lf ",f[i]);
20     printf("\na=\n");
21     for(int i=1;i<=n;++i)
22     {
23         for(int j=1;j<=n;++j)
24           printf("%.3lf ",a[i][j]);
25         printf("\n");
26     }
27     printf("\n");
28 }
29 
30 int main(){
31     //freopen("data0.in","r",stdin);
32     scanf("%d%d%d",&n,&m,&k);
33     for(int i=1;i<=n;++i)
34       scanf("%lf",&f[i]);
35     a[1][1]=((dd)m-1.0)/(dd)m;
36     a[n][1]=1.0/(dd)m;
37     for(int i=2;i<=n;++i)
38     {
39         a[i][i]=((dd)m-1.0)/(dd)m;
40         a[i-1][i]=1.0/(dd)m;
41     }
42     
43     while(k)
44     {
45         if(k&1)
46         {
47             for(int i=1;i<=n;++i)
48             {
49                 temp[i]=0;
50                 for(int k=1;k<=n;++k)
51                   temp[i]+=f[k]*a[k][i];
52             }
53             for(int i=1;i<=n;++i)
54               f[i]=temp[i];
55         }
56         for(int j=1;j<=n;++j)
57       {
58             temp[j]=0;
59             for(int k=1;k<=n;++k)
60               temp[j]+=a[1][k]*a[k][j];
61         }
62         for(int j=1;j<=n;++j)
63           a[1][j]=temp[j];
64         for(int i=2;i<=n;++i)
65         {
66             a[i][1]=a[i-1][n];
67           for(int j=2;j<=n;++j)
68             a[i][j]=a[i-1][j-1];
69         }
70         //out11();
71         k>>=1;
72     }
73     
74     for(int i=1;i<=n;++i)
75       printf("%.3lf\n",f[i]);
76     
77     //while(1);
78     return 0;
79 }
80     
code

 

posted @ 2017-07-27 21:09  A_LEAF  阅读(192)  评论(0编辑  收藏  举报