弱題(循環矩陣1)
阿新 • • 發佈:2017-07-29
submit 操作 多少 sub nbsp 要求 printf cheng 輸出
提交: 46 解決: 28
[提交][狀態][討論版]
ai,表示初始標號為i的球有ai個。
問題 D: 弱題
時間限制: 1 Sec 內存限制: 128 MB提交: 46 解決: 28
[提交][狀態][討論版]
題目描述
有M個球,一開始每個球均有一個初始標號,標號範圍為1~N且為整數,標號為i的球有ai個,並保證Σai = M。 每次操作等概率取出一個球(即取出每個球的概率均為1/M),若這個球標號為k(k < N),則將它重新標號為k + 1;若這個球標號為N,則將其重標號為1。(取出球後並不將其丟棄) 現在你需要求出,經過K次這樣的操作後,每個標號的球的期望個數。輸入
第1行包含三個正整數N,M,K,表示了標號與球的個數以及操作次數。 第2行包含N個非負整數輸出
應包含N行,第i行為標號為i的球的期望個數,四舍五入保留3位小數。樣例輸入
2 3 2
3 0
樣例輸出
1.667
1.333
這道題很容易就能想到用矩陣快速冪,但n^3的時間復雜度顯然是過不去,然後根據DP方程 f[i]=a/n*f[i-1]+(1-b/n)*f[i];所以每一項的轉移都是從本位和前一位轉移而來的,那麽在構建出來的矩陣,無論自乘多少次都能地i+1行是由i行右移的得到的,最後一位到第一位;那麽就可以用矩陣的第一行來表示整個矩陣,我實現的有些麻煩,我有把整個矩陣都重現了出來,其實可以直接由一個關系直接轉移,還有進一步的優化空間;
(
1 #include<cmath> 2 #include<ctime> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 int n,m,K; 10 int num[1010]; 11 double f[1010]; 12 double a[1010][1010]; 13 doublecc[1010]; 14 double b[1010][1010]; 15 void cheng1(){ 16 memset(cc,0,sizeof(cc)); 17 for(int i=1;i<=n;i++){ 18 for(int j=1;j<=n;j++){ 19 cc[i]+=b[j][i]*f[j]; 20 } 21 } 22 for(int i=1;i<=n;i++) 23 f[i]=cc[i]; 24 } 25 double dd[1010][1010]; 26 void cheng2(){ 27 memset(dd,0,sizeof(dd)); 28 for(int i=1;i<=n;i++){ 29 for(int j=1;j<=n;j++){ 30 dd[1][i]+=a[1][j]*a[j][i]; 31 } 32 } 33 for(int i=1;i<=n;i++) 34 a[1][i]=dd[1][i]; 35 for(int i=2;i<=n;i++){ 36 for(int j=1;j<=n;j++){ 37 if(j==1){ 38 a[i][j]=a[i-1][n]; 39 continue; 40 } 41 a[i][j]=a[i-1][j-1]; 42 } 43 } 44 } 45 void cheng3(){ 46 memset(dd,0,sizeof(dd)); 47 for(int i=1;i<=n;i++){ 48 for(int j=1;j<=n;j++){ 49 dd[1][i]+=a[1][j]*b[j][i]; 50 //if(i==1) cout<<"--->"<<a[1][j]<<" "<<b[j][i]<<endl; 51 } 52 } 53 for(int i=1;i<=n;i++){ 54 b[1][i]=dd[1][i]; 55 } 56 for(int i=2;i<=n;i++){ 57 for(int j=1;j<=n;j++){ 58 if(j==1){ 59 b[i][j]=b[i-1][n]; 60 continue; 61 } 62 b[i][j]=b[i-1][j-1]; 63 } 64 } 65 //while(1); 66 } 67 int main(){ 68 //freopen("a.in","r",stdin); 69 // freopen("1.out","w",stdout); 70 scanf("%d%d%d",&n,&m,&K); 71 for(int i=1;i<=n;i++){ 72 scanf("%d",&num[i]); 73 f[i]=num[i]; 74 } 75 for(int i=1;i<=n;i++) b[i][i]=1; 76 a[1][1]+=(double)(m-1)/m; 77 a[n][1]+=(double)1/m; 78 for(int i=2;i<=n;i++){ 79 a[i][i]+=(double)(m-1)/m; 80 a[i-1][i]+=(double)1/m; 81 } 82 /* 83 for(int i=1;i<=n;i++){ 84 for(int j=1;j<=n;j++){ 85 cout<<a[i][j]<<" "; 86 } 87 cout<<endl; 88 }*/ 89 while(K){ 90 if(K&1){ 91 cheng3(); 92 } 93 cheng2(); 94 K=K>>1; 95 } 96 cheng1(); 97 for(int i=1;i<=n;i++){ 98 printf("%.3lf\n",f[i]); 99 } 100 return 0; 101 }
循環矩陣留坑)
弱題(循環矩陣1)