这个题目看网上好多题解都是直接O(n*m)卡过。我是这么做的。
对于m次操作,统计每个w的次数。然后对每个w做矩阵乘法。
这样直接做矩阵乘法是会TLE的。
又由于这里的矩阵很特殊,一次乘法可以降维成O(n^2)。
--------------------------
怎么降维的可以这样模拟下:
a b c a b c a*a+2bc c*c+2ab b*b+2ac
c a b * c a b = b*b+2ac a*a+2bc c*c+2ab
b c a b c a c*c+2ab b*b+2ac a*a+2bc
注意到原矩阵的每一行(除了第一行)都是上一行向右平移一个单位的结果,而相乘得到的矩阵也满足这个性质。
那么做一次矩阵乘法的时候,就只用算出结果矩阵的第一行,然后下面的每一行直接可由上一行得到。
复杂度降为了O(n^2)。
-------------------------
所以一个总的复杂度<O(n^2 * log1000000 * 100)=8千万.
不到2000msAC了^_^
1 #include<cstdio> 2 #include<iostream> 3 #include<iomanip> 4 #include<cstring> 5 #include<cmath> 6 #include<set> 7 #include<map> 8 #include<queue> 9 #include<stack> 10 #include<string> 11 #include<vector> 12 #include<ctype.h> 13 #include<algorithm> 14 using namespace std; 15 typedef long long LL; 16 #define FF(i,x) for(i=1;i<=x;i++) 17 const int N = 205; 18 19 double cMat[N][N],retMat[N][N]; 20 21 void matrixMul1(double A[][N],double B[][N],int a,int b) 22 { 23 double buff[N][N]={}; 24 int i,j,k; 25 FF(i,a) FF(k,a) FF(j,b) 26 buff[i][j] = buff[i][j] + A[i][k]*B[k][j]; 27 FF(i,a) FF(j,b) B[i][j]=buff[i][j]; 28 } 29 30 void matrixMul2(double A[][N],double B[][N],int a,int b) 31 { 32 double buff[N][N]={}; 33 for(int j=1;j<=a;j++) 34 { 35 for(int k=1;k<=a;k++) 36 buff[1][j]+=A[1][k]*B[k][j]; 37 } 38 for(int i=2;i<=a;i++) 39 { 40 for(int j=2;j<=a;j++) buff[i][j]=buff[i-1][j-1]; 41 buff[i][1]=buff[i-1][a]; 42 } 43 int i,j; 44 FF(i,a) FF(j,b) B[i][j]=buff[i][j]; 45 } 46 47 void matrixFastPow(int p,int n) 48 { 49 for(;p;p>>=1) 50 { 51 if( p&1 ) matrixMul1(cMat,retMat,n,1); 52 matrixMul2(cMat,cMat,n,n); 53 } 54 } 55 56 int amount[105]; 57 58 int main() 59 { 60 int n,m,l,r; 61 int w; 62 63 while( scanf("%d%d%d%d",&n,&m,&l,&r),n||m||l||r ) 64 { 65 memset(amount,0,sizeof(amount)); 66 for(int i=0;i<m;i++) 67 { 68 scanf("%d",&w); 69 amount[w]++; 70 } 71 for(int i=1;i<=n;i++) 72 if( i<l || i>r ) retMat[i][1]=0.0; 73 else retMat[i][1]=1.0; 74 for(int i=1;i<=100;i++) 75 if( amount[i] ) 76 { 77 for(int p=1;p<=n;p++) 78 for(int q=1;q<=n;q++) 79 cMat[p][q]=0.0; 80 for(int j=1;j<=n;j++) 81 { 82 int a=(j-i); 83 while( a<=0 ) a+=n; 84 int b=(j+i); 85 while( b>n ) b-=n; 86 cMat[j][a]+=0.5; 87 cMat[j][b]+=0.5; 88 } 89 matrixFastPow(amount[i],n); 90 } 91 92 printf("%.4f ",retMat[1][1]); 93 } 94 return 0; 95 }