Codebegin
- #include "stdafx.h"
- #include <stdio.h>
- #include <memory.h>
- __int64 fb[1005];/* n很大的时候数组会溢出 */
- __int64 fib0(int n)/*自顶而下递归*/
- {
- return (2>n)?(__int64)n /*达到递归基直接取值*/
- :fib0(n-1)+fib0(n-2);
- }
- __int64 fib1(int n)/*memoization*/
- {
- if(0==n)
- return (__int64)(fb[0]=0);
- if(1==n)
- return (__int64)(fb[1]=1);
- if(fb[n]>=0){/*不是-1说明之前算过了,直接返回,剪掉一颗子树节省大量时间*/
- return (__int64)(fb[n]);
- }else{
- return fb[n]=fib1(n-1)+fib1(n-2);
- }
- }
- __int64 fib2(int n)/*自底而上迭代*/
- {
- __int64 f=0;
- __int64 g=1;
- while(0<n--)
- {
- g=g+f;
- f=g-f;
- }
- return f;
- }
- /* c = a*b
- a[0][0] a[0][1] b[0][0] b[0][1] c[0][0] c[0][1]
- a[1][0] a[1][1] b[1][0] b[1][1] c[1][0] c[1][1]
- i=0 j=0: i k k j
- c[0][0]+=a[0][0]*b[0][0] k=0
- c[0][0]+=a[0][1]*b[1][0] k=1
- i=0 j=1: i k k j
- c[0][1]+=a[0][0]*b[0][1] k=0
- c[0][1]+=a[0][1]*b[1][1] k=1
- i=1 j=0: i k k j
- c[1][0]+=a[1][0]*b[0][0] k=0
- c[1][0]+=a[1][1]*b[1][0] k=1
- i=1 j=1: i k k j
- c[1][1]+=a[1][0]*b[0][1] k=0
- c[1][1]+=a[1][1]*b[1][1] k=1
- */
- void multi_mtrx1(__int64 a[2][2],__int64 b[2][2])
- {
- int i,j,k;
- __int64 c[2][2];
- memset(c,0,sizeof(c));
- for(i=0;i<2;i++){
- for(j=0;j<2;j++){
- for(k=0;k<2;k++){
- c[i][j]+=a[i][k]*b[k][j];
- //c[i][j]%=c[i][j];/*加上这一句*/
- }
- }
- }
- for(i=0;i<2;i++)
- for(j=0;j<2;j++)
- a[i][j]=c[i][j];
- }
- /* 这种方法比较难于理解,好处是如果n比较大,且矩阵比较稀疏的时候可以剪枝
- i=0 k=0: i k k j
- c[0][0]+=a[0][0]*b[0][0] j=0
- c[0][1]+=a[0][0]*b[0][1] j=1
- i=0 k=1: i k k j
- c[0][0]+=a[0][1]*b[1][0] j=0
- c[0][1]+=a[0][1]*b[1][1] j=1
- i=1 k=0: i k k j
- c[1][0]+=a[1][0]*b[0][0] j=0
- c[1][1]+=a[1][0]*b[0][1] j=1
- i=1 k=1: i k k j
- c[1][0]+=a[1][1]*b[1][0] j=0
- c[1][1]+=a[1][1]*b[1][1] j=1
- */
- void multi_mtrx2(__int64 a[2][2],__int64 b[2][2])
- {
- int i,j,k;
- __int64 c[2][2];
- memset(c,0,sizeof(c));
- for(i=0;i<2;i++){
- for(k=0;k<2;k++)
- {
- if(0==a[i][k])/*剪枝,但其实对于2x2的矩阵意义不大*/
- continue;
- for(j=0;j<2;j++){
- c[i][j]+=a[i][k]*b[k][j];
- //c[i][j]%=c[i][j];/*加上这一句*/
- }
- }
- }
- for(i=0;i<2;i++)
- for(j=0;j<2;j++)
- a[i][j]=c[i][j];
- }
- void quick_pow(__int64 rslt[2][2],int power)
- {
- __int64 fi[2][2];
- rslt[0][0]=rslt[1][1]=1;
- rslt[0][1]=rslt[1][0]=0;
- fi[1][1]=0;
- fi[0][0]=fi[0][1]=fi[1][0]=1;
- while(power){
- if(power&1)
- multi_mtrx2(rslt,fi);
- multi_mtrx2(fi,fi);
- power>>=1;
- }
- }
- __int64 fib3(int n)
- {
- __int64 rslt[2][2];
- quick_pow(rslt,n);
- return rslt[0][1];
- }
- int main(int argc, char* argv[])
- {
- int n;
- memset(fb,-1,sizeof(fb));
- /* 最大n为103,超出程序就不会给出正确结果 */
- while(-1!=scanf("%d",&n) && -1!=n)
- {
- printf("fib3 result is %lld\n",fib1(n));
- printf("fib3 result is %lld\n",fib2(n));
- printf("fib4 result is %lld\n",fib3(n));
- }
- return 0;
- }
最后附上POJ的一道题,该题只需要计算Fn mod 10000, 这样在矩阵乘法的函数当中
加上mod操作,而所有是数组也不用__int64, 用int 就可以
c[i][j]+=a[i][k]*b[k][j]; =>
c[i][j]+=a[i][k]*b[k][j];
c[i][j]%=c[i][j];/*加上这一句*/
「POJ3070」Fibonacci
Description
In the Fibonacci integer sequence, F = 0, F = 1, and F = F + F for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
An alternative formula for the Fibonacci sequence is
.
Given an integer n, your goal is to compute the last 4 digits of F.
Input
The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number ?1.
Output
For each test case, print the last four digits of F. If the last four digits of F are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print F mod 10000).
0
9
999999999
1000000000
-1
Sample Output
0
34
626
6875
Note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:
.