斐波那契主要分为以下题型:
1.求具体某项的值(一般在45项以内,打表即可)
2.求具体某一项模K(通常是个大数项,一般采用矩阵法)
3.求斐波那契前几位数字(例如:HDU 的 3117 题)
4.求解 Fibonacci 的后多少位,这个和取模类似
5.求前n项和(矩阵法)
最常用最好用的——矩阵法
需要用到线性代数矩阵相乘的方法
例1:HIT 2060
As we know , the Fibonacci numbers are defined as follows:
""""
Given two numbers a and b , calculate . """"
Input
The input contains several test cases. Each test case consists of two non-negative integer numbers a and b (0 ≤ a ≤ b ≤1,000,000,000). Input is terminated by a = b = 0.
Output
For each test case, output S mod 1,000,000,000, since S may be quite large.
Sample Input
1 1 3 5 10 1000 0 0Sample Output
1 16 496035733s(n)=s(n-1)+F(n-1)+F(n-2)
{ 0 , 1 , 0 { F(0) { F(1)
1 , 1 , 0 x F(1) = F(2)
0 , 1 , 1 } s(1) } s(2) }
以此类推
{ 0 , 1 , 0 ^n-1 { F(0) { F(1)
1 , 1 , 0 x F(1) = F(2)
0 , 1 , 1 } s(1) } s(2) }
#include <iostream>
#define mod 1000000000
#define max 3
using namespace std;
typedef struct //建立3x3的矩阵
{
long long m[max][max];
}matrix;
matrix p={0,1,0, //按之前推导的定义矩阵p
1,1,0,
0,1,1};
matrix q={1,0,0, //矩阵q为单位阵
0,1,0,
0,0,1};
matrix juzhenchengfa(matrix a,matrix b) //矩阵乘法
{
int i,j,k;
matrix c;
for(i=0;i<max;i++)
{
for(j=0;j<max;j++)
{
c.m[i][j]=0;
for(k=0;k<max;k++)
{
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
}
c.m[i][j]=(c.m[i][j]%mod+mod)%mod;
}
}
return c;
}
matrix quickpow(long long n)
{
matrix a=p,b=q;
while(n>=1)
{
if(n&1) b=juzhenchengfa(a,b);
n>>=1;
a=juzhenchengfa(a,a);
}
return b;
}
int main()
{
long long s,e,sum,sum1;
matrix tmp,tmp1;
while(cin>>s>>e)
{
if(s==0&&e==0) break;
tmp=quickpow(e);
sum=(tmp.m[2][0]+tmp.m[2][1]+2*tmp.m[2][2])%mod;
tmp1=quickpow(s-1);
sum1=(tmp1.m[2][0]+tmp1.m[2][1]+2*tmp1.m[2][2])%mod;
cout<<(sum-sum1)%mod<<endl;
}
}
例2:As we all known , the Fibonacci series : F(0) = 1, F(1) = 1, F(N) = F(N - 1) + F(N - 2) (N >= 2).Now we define another kind of Fibonacci : f(0) = 1 , f(1) = 1 , f(N) = X * f(N - 1) + Y * f(N - 2) (N >= 2).And we want to Calculate S(N) , S(N) = f(0)2 +f(1)2+……+f(n)2.
Input :There are several test cases. Each test case will contain three integers , N, X , Y, N(2<= N <= 2^31 – 1 X : 2<= X <= 2^31– 1 Y : 2<= Y <= 2^31 – 1 )
Output :For each test case , output the answer of S(n).If the answer is too big , divide it by 10007 and give me the reminder.
Sample Input : 2 1 1
3 2 3
Sample Output : 6
196
{ 1, 1, 0, 0, { s(n-1) { s(n) { s(n-1)+f^2(n-1)
0,x^2,y^2,2*x*y, f^2(n-1) f^2(n) x^2*f^2(n-1)+2*x*y*f(n-1)*f(n-2)+y^2*f^2(n-2)
0, 1, 0, 0, x f^2(n-2) = f^2(n-1) = f^2(n-1)
0, x^2, 0, y } f(n-1)*f(n-2) } f(n)*f(n-1)} x^2*f(n-1)+y*f(n-1)*f(n-2) }
#include <iostream>
#include <stdio.h>
#include <cstring>
#define Mod 10007
using namespace std;
const int MAX = 4;
typedef struct
{
int m[MAX][MAX];
} Matrix;
Matrix P={1,1,0,0,
0,0,0,0,
0,1,0,0,
0,0,0,0};
Matrix I={1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1};
Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法
{
int i,j,k;
Matrix c;
for (i = 0 ; i < MAX; i++)
for (j = 0; j < MAX;j++)
{
c.m[i][j] = 0;
for (k = 0; k < MAX; k++)
c.m[i][j] += (a.m[i][k]* b.m[k][j])%Mod;
c.m[i][j] %= Mod;
}
return c;
}
Matrix quickpow(long long n)
{
Matrix m = P, b = I;
while (n >= 1)
{
if (n & 1)
b = matrixmul(b,m);
n = n >> 1;
m = matrixmul(m,m);
}
return b;
}
int main()
{ int n,x,y,sum;
Matrix b;
while(cin>>n>>x>>y)
{
sum=0;
x=x%Mod;
y=y%Mod;
P.m[1][1]=(x*x)%Mod;
P.m[1][2]=(y*y)%Mod;
P.m[1][3]=(2*x*y)%Mod;
P.m[3][1]=x;
P.m[3][3]=y;
b=quickpow(n);
for(int i=0;i<4;i++)
sum+=b.m[0][i]%Mod;
cout<<sum%Mod<<endl;
}
return 0;
}
求前n位或后n位类型题
后n位即对10^n取余后printf("%0nd\n");前n位的求法略难,领会不了就记模板吧~
例:HDU 3117

What is the numerical value of the nth Fibonacci number?
There is no special way to denote the end of the of the input, simply stop when the standard input terminates (after the EOF).
0 1 2 3 4 5 35 36 37 38 39 40 64 65
0 1 1 2 3 5 9227465 14930352 24157817 39088169 63245986 1023...4155 1061...7723 1716...7565
思路~:斐波那契数列前50项左右<10^8打表输出即可,大于10^8的用矩阵法计算值,后四位——对10000取余即可(注意%04d输出四位),
前四位求法:
123456.32=1234.56*10^2
s=d.xxx*10^(len-4)
log10(s)=log10(d.xxxxx)+log10(10^(len-4))=log10(d.xxxx)+len-4;
log10(s)+4-len=log10(d.xxxx)
d.xxxx=10^(log10(s)+4-len)
s=(1/sqrt(5))*[(1+sqrt(5))/2.0]^n;
len=(int)log10(s)+1;
d.xxxx=10^(log10(s)+4-((int)log10(s)+1))=10^(log10(s)-(int)log10(s)+3); //看不懂,直接上代码
#include <iostream>
#include <stdio.h>
#include <math.h>
#define Mod 10000
using namespace std;
long long f[100];
const int MAX = 2;
typedef struct
{
long long m[MAX][MAX];
} Matrix;
Matrix P = {0,1,
1,1};
Matrix I = {1,0,
0,1};
Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法
{
int i,j,k;
Matrix c;
for (i = 0 ; i < MAX; i++)
for (j = 0; j < MAX;j++)
{
c.m[i][j] = 0;
for (k = 0; k < MAX; k++)
c.m[i][j] += (a.m[i][k] * b.m[k][j])%Mod;
c.m[i][j] %= Mod;
}
return c;
}
Matrix quickpow(long long n)
{
Matrix m = P, b = I;
while (n >= 1)
{
if (n & 1)
b = matrixmul(b,m);
n = n >> 1;
m = matrixmul(m,m);
}
return b;
}
int main()
{
double log_s=0.0;
Matrix tmp;
int n,bit=0;
f[0]=0;f[1]=1;
for(int i=2;i<=50;i++)
{
f[i]=f[i-1]+f[i-2];
if (f[i]>=100000000)
{ bit=i-1;break;}
}
while(cin>>n)
{
if (n<=bit) cout<<f[n]<<endl;
if (n>bit)
{
tmp=quickpow(n);
int ans_e=tmp.m[0][1];
log_s=log10(1.0/sqrt(5)) +(double)n*log10((1.0+sqrt (5))/2.0);
int ans_s=(int)(pow(10,log_s-(int)log_s+3));
cout<<ans_s<<"...";
printf("%04d\n",ans_e);
}
}
return 0;
}