弱题
(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