hdu4576 概率dp n^2的矩阵

这个题目看网上好多题解都是直接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\n",retMat[1][1]);
93     }
94     return 0;
95 }
View Code

 

posted @ 2013-08-10 21:08  kiwi_bird  阅读(787)  评论(0编辑  收藏  举报