【題目描述】
我們知道斐波那契數列0 1 1 2 3 5 8 13……
數列中的第i位為第i-1位和第i-2位的和(規定第0位為0,第一位為1)。
求斐波那契數列中的第n位mod 10000的值。
【分析】
這是我們熟悉的斐波那契數列,原來呢我們是遞推求值的嘛,當然這是最水的想法~~可是!這里的n很大誒,有10^9,for一遍肯定是不可以的咯。
於是,我學會了用矩陣乘法求斐波那契數列(貌似是很經典的)。
作為初學者的我覺得十分神奇!!
好,我們來看:
我們每次存兩個數f[i-1]和f[i-2],表示數列中的第i-1個數和第i-2的數,如何用這兩個數推出我們下一次要存的兩個數f[i]和f[i-1]呢,嗯,題目已經說得很清楚了:
f[i-1]=f[i-1]
f[i]=f[i-1]+f[i-2]
可能你會覺得第一句有一點廢話,但是是有不一樣的意義的,這體現了遞推的過程,就是說我們每次掃兩個數,根據前面的兩個數推出后面的兩個數,這個思想在后面我做的一題——poj3734中有更好的體現。根據這個我們可以建一個2*2的矩陣A
| 1 | 1 |
| 1 | 0 |
然后把我們每次存的兩個數放在另一個矩陣B里面:
| f[i-1] |
| f[i-2] |
那么把這兩個矩陣相乘就可以得到另一個矩陣:
| f[i] |
| f[i-1] |
這樣就可以得到f[i]了,至於為什么乘了之后會變成這兩個數,我們根據矩陣乘法的乘法規律可以很容易推出來。
這樣子的話,我們每次用A*B替換B,最后得到的矩陣的第一個數就是f[n]了。
那么,矩陣乘法的優越性究竟體現在哪里呢。其實,矩陣乘法只是體現了我們從之前求的數到現在要求的數的遞推過程,就是說矩陣乘法可以完成多個元素的遞推。不過這個我們用普通的遞推就可以實現的啊~~認真想想我們就能發現,我們在矩陣乘法的過程中把上見面的A矩陣自己相乘了很多遍。就是說,我們可以求A矩陣的冪最后乘上B矩陣,既然要求冪,矩陣乘法滿足結合律,那么我們就可以用快速冪啦~~矩陣乘法的優越性就體現在這里:在遞推過程變成不斷乘以一個矩陣,然后用快速冪快速求得從第一個到第n個的遞推式,這樣子就可以在短時間內完成遞推了。
哇塞,人類的智商啊~~讓我們繼續膜拜那些智商正無窮的大神吧,orz,orz……
之前寫的快速冪都是遞歸式的,現在終於學會新的快速冪寫法,紀念一下:
1 while(n) 2 { 3 if(n&1) b=a*b; 4 a=a*a; 5 n>>=1; 6 }
為什么這樣打快速冪可以呢,把指數換成二進制想一想,就可以發現了。
接下來貼代碼,結構體真心好用,代碼好看多了~~嗯...另外做題目的時候要注意細節!!
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #define Mod 10000 5 6 struct node 7 { 8 int v[3][3]; 9 int m,l; 10 }; 11 12 node get_mul(node a,node b) 13 { 14 node c; 15 c.m=a.m;c.l=b.l; 16 for(int i=1;i<=c.m;i++) 17 for(int j=1;j<=c.l;j++) 18 { 19 c.v[i][j]=0; 20 for(int k=1;k<=a.l;k++) 21 c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%Mod; 22 } 23 return c; 24 } 25 26 int main() 27 { 28 freopen("a.in","r",stdin); 29 freopen("a.out","w",stdout); 30 int n; 31 while(1) 32 { 33 scanf("%d",&n); 34 if(n==0) {printf("0\n");continue;} 35 if(n==-1) break; 36 node a,b,c; 37 a.m=a.l=2,a.v[1][1]=1,a.v[1][2]=1,a.v[2][1]=1,a.v[2][2]=0; 38 b.m=b.l=2,b.v[1][1]=1,b.v[1][2]=0,b.v[2][1]=0,b.v[2][2]=1; 39 c.m=2,c.l=1,c.v[1][1]=1,c.v[2][1]=0; 40 n--; 41 while(n) 42 { 43 if(n&1) b=get_mul(a,b); 44 a=get_mul(a,a); 45 n>>=1; 46 } 47 b=get_mul(b,c); 48 printf("%d\n",b.v[1][1]); 49 } 50 return 0; 51 }
打表打得好惡心啊!!
2015-09-19 10:33:36
