【BZOJ 2510】 2510: 弱题 (矩阵乘法、循环矩阵的矩阵乘法)
2510: 弱题
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 374 Solved: 196Description
有M个球,一开始每个球均有一个初始标号,标号范围为1~N且为整数,标号为i的球有ai个,并保证Σai = M。每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为k(k < N),则将它重新标号为k + 1;若这个球标号为N,则将其重标号为1。(取出球后并不将其丢弃)现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数。Input
第1行包含三个正整数N,M,K,表示了标号与球的个数以及操作次数。第2行包含N个非负整数ai,表示初始标号为i的球有ai个。Output
应包含N行,第i行为标号为i的球的期望个数,四舍五入保留3位小数。Sample Input
2 3 2
3 0
Sample Output
1.667
1.333
HINT
【样例说明】
第1次操作后,由于标号为2球个数为0,所以必然是一个标号为1的球变为标号为2的球。所以有2个标号为1的球,有1个标号为2的球。
第2次操作后,有1/3的概率标号为2的球变为标号为1的球(此时标号为1的球有3个),有2/3的概率标号为1的球变为标号为2的球(此时标号为1的球有1个),所以标号为1的球的期望个数为1/3*3+2/3*1 = 5/3。同理可求出标号为2的球期望个数为4/3。
【数据规模与约定】
对于10%的数据,N ≤ 5, M ≤ 5, K ≤ 10;
对于20%的数据,N ≤ 20, M ≤ 50, K ≤ 20;
对于30%的数据,N ≤ 100, M ≤ 100, K ≤ 100;
对于40%的数据,M ≤ 1000, K ≤ 1000;
对于100%的数据,N ≤ 1000, M ≤ 100,000,000, K ≤ 2,147,483,647。
Source
【分析】
综合题表里面目测的一道【稀少的】可做题。。
显然,矩阵乘法嘛。。$f[i][j]=f[i-1][j]*\dfrac{m-1}{m}+f[i-1][j-1]*\dfrac{1}{m}$
然后一个厉害的东西就是A,B是循环矩阵(就是矩阵的下一行是上一行循环右移一位得到的),那么A*B=C的C也是循环矩阵。
只需求第一行就可以求出整个C。
所以是$n^2 log$
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1010 8 9 int a[Maxn]; 10 int n,m,k; 11 12 struct node 13 { 14 double w[Maxn][Maxn]; 15 }t[5]; 16 17 void mul(int x,int y,int z) 18 { 19 for(int i=1;i<=n;i++) 20 for(int j=1;j<=n;j++) t[2].w[i][j]=0; 21 for(int k=1;k<=n;k++) 22 for(int j=1;j<=n;j++) 23 t[2].w[1][j]+=t[y].w[1][k]*t[z].w[k][j]; 24 for(int j=1;j<=n;j++) t[x].w[1][j]=t[2].w[1][j]; 25 for(int i=2;i<=n;i++) 26 { 27 for(int j=1;j<=n;j++) 28 t[x].w[i][j]=t[x].w[i-1][j-1==0?n:j-1]; 29 } 30 } 31 32 void qpow(int b) 33 { 34 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) t[1].w[i][j]=0; 35 for(int i=1;i<=n;i++) t[1].w[i][i]=1.0; 36 while(b) 37 { 38 if(b&1) mul(1,0,1); 39 mul(0,0,0); 40 b>>=1; 41 } 42 } 43 44 int main() 45 { 46 scanf("%d%d%d",&n,&m,&k); 47 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 48 for(int i=1;i<=n;i++) 49 { 50 for(int j=1;j<=n;j++) t[0].w[i][j]=0; 51 t[0].w[i][i]=1.0-1.0/m; 52 t[0].w[i][i-1==0?n:i-1]=1.0/m; 53 } 54 qpow(k); 55 for(int i=1;i<=n;i++) 56 { 57 double ans=0; 58 for(int j=1;j<=n;j++) 59 { 60 ans+=a[j]*t[1].w[i][j]; 61 } 62 printf("%.3lf\n",ans); 63 } 64 return 0; 65 }
2017-04-10 20:47:14