Sicily E1_fib1 斐波那契数列取模(大数)分治算法


思路与源代码参考地址在此


(1)由于有如下性质:

(n*m)%c=[(n%c)*(m%c)]%c

(n+m)%c=[(n%c)+(m%c)]%c ,

计算过程中可以随时取模,而不影响最终的结果。


(2)利用矩阵求斐波那契数列:

(3)

二分的原理:要求矩阵的N次方A(N),设i=N/2。若N%2==1, 则 A(N)=A(i)*A(i)*A(1);若N%2==0, 则 A(N)=A(i)*A(i)

基于二进制的原理:将N拆为二进制数,譬如13=1101那么 A^13= A^8 * A^4 * A^1 (这里^表示幂运算)


也就是说,由A^1开始,自乘得到A^2,然后自乘得到A^4,如果N对应位为1,则将这个结果乘到目标上去
这样的话,将所有乘法改为模乘,就可以得到一个较大Fibonacci数除以M的余数


实现代码:


#include<iostream>
using namespace std;

#define mod 1000000007
// f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)
int tempA, tempB, tempC, tempD;
void func(int n, int &a, int &b, int &c, int &d){
    if (n == 1){
        a = 0;
        b = c = d = 1;
        return;
    }
    if (n % 2 == 0){
        func(n / 2, a, b, c, d);
        tempA = a*a + b*c;
        tempB = b*(a + d);
        tempC = c*(a + d);
        tempD = c*b + d*d;
        a = tempA % mod;
        b = tempB % mod;
        c = tempC % mod;
        d = tempD % mod;
        return;
    }
    else{
        func(n / 2, a, b, c, d);
        tempA = b*(a + d);
        tempB = a*a + b*(a + c + d);
        tempC = c*b + d*d;
        tempD = c*(a + b + d) + d*d;
        a = tempA % mod;
        b = tempB % mod;
        c = tempC % mod;
        d = tempD % mod;
        return;
    }
}
int main(){
    int n;
    while (cin >> n&&n != 0){
        int a, b, c, d;
        if (n <= 2){
            cout << 1 << endl;
            continue;
        }
        else n -= 2;
        func(n, a, b, c, d);
        cout << (b + d) % mod << endl;
    }
    return 0;
}           


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值