Time limit : 1 s
Memory limit : 32 mb
Problem Description
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 0
Sample Output
1
16
496035733
题意:
求斐波那契数列第a项到第b项的和对1000000000取模的结果。
题解:
设g[x]为斐波那契数列第0项到第x项的和。则题目答案为g[b]-g[a-1](显然),那么g[x]的值为多少?
显然,我们可以知道g(1)=f[1]+f[0]=2=f[3]-1
那么开始数学归纳法(:D)
设当x=k时,g[k]=f[k+2]-1
那么当x=k+1时,g[k+1]=f[k+2]-1+f[k+1]=f[k+3]-1
得证 g[x]=f[x+2]-1
那么剩下的只需要求f[a+1]和f[b+2]的值就行了,这个过程可以使用矩阵乘法。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define LiangJiaJun main
#define INF 2100000000
#define MOD 1000000000
using namespace std;
int n,k,f[14];
struct M{long long m[14][14],l;}rev1,rev2,A,B;
M mul(M X, M Y){
M G;
G.l=X.l;
for(int i=1;i<=X.l;i++)
for(int j=1;j<=X.l;j++)G.m[i][j]=0;
for(int i=1;i<=X.l;i++)
for(int j=1;j<=X.l;j++)
for(int k=1;k<=X.l;k++)
G.m[i][j]=(G.m[i][j]+X.m[i][k]*Y.m[k][j])%MOD;
return G;
}
M Fpow(M GE,int pe){
if(pe == 1)return GE;
M temp = Fpow(GE,pe>>1);
if(pe & 1)return mul(GE,mul(temp,temp));
else return mul(temp,temp);
}
void reset(){
A.l=B.l=rev1.l=rev2.l=2;
rev1.m[1][1]=1;rev1.m[1][2]=1;
rev1.m[2][1]=1;rev1.m[2][2]=0;
rev2.m[1][1]=1;rev2.m[1][2]=1;
rev2.m[2][1]=1;rev2.m[2][2]=0;
A.m[1][1]=1;A.m[1][2]=1;
A.m[2][1]=0;A.m[2][2]=0;
B.m[1][1]=1;B.m[1][2]=1;
B.m[2][1]=0;B.m[2][2]=0;
}
int LiangJiaJun (){
int a,b;
reset();
while(scanf("%d%d",&a,&b)!=EOF){
if(a == 0 && b == 0)break;
a +=3 ; b +=3;
M rv;
long long tipA , tipB;
if(a-1 <= 2) tipA = 1;
else{
rv = mul(A,Fpow(rev1,a-3));
tipA = (rv.m[1][1]+MOD-1)%MOD;
}
if(b <= 2) tipB = 1;
else {
rv = mul(B,Fpow(rev2,b-2));
tipB = (rv.m[1][1]+MOD-1)%MOD;
}
printf("%lld\n",(tipB+MOD-tipA)%MOD);
}
return 0;
}