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;
-
}
Codeend
最后附上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, F0 = 0, F1 = 1, and Fn = Fn ? 1 + Fn ? 2 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 Fn.
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 Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).
Sample Input
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:
.
阅读(2984) | 评论(0) | 转发(0) |