[HOJ2060]Fibonacci Problem Again

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值