矩阵快速幂 !

Description

一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?这个问题难不倒农夫 John ,但当地的农夫 Jack 要有意为难他。刚开始时, John 养了一对小兔子, Jack 自第 3 个月起送 John 若干对兔子,假定第 n 个月送  n 对兔子。兔子繁殖后形成新的兔子序列:
F= Fn-1 + Fn-2 +n ,( n>1) F1=1  F=1
给定一个整数 n ,求 Fn 是多少?上述问题, John 自然是答不上来,现在请你帮助。

Input

多组数据,每组一行,其上有一个整数 n(0<n<=10000000000000)

Output

每组输出一行,输出 Fn (mod 100000007) 

Sample Input

5

Sample Output

20

首先构造矩阵。

|f(n)    |                        | 1  1  1  0  |                | f(n-1)  |

|f(n-1) |              =        | 1  0  0  0  |       *        | f(n-2) |

|n+1    |                       | 0  0  1  1  |                 |    n     |

| 1       |                       | 0  0  0  1  |                |     1     |

     ans                                 temp                     begin


ans 矩阵 和 begin 矩阵两个的关系是前后项的关系,即n变成n+1.

其余参考快速幂即可。



#include<iostream>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int mod = 100000007;
struct matrix{			//构造矩阵,默认元素全为0.
    long long m[4][4];       //wa了一次,主要不能用int
    matrix(){
        memset(m,0,sizeof(m));
    }
    void ini(){  		// 初始化函数,初始化矩阵为单位阵
        for(int i=0;i<4;i++){
            m[i][i] = 1;
        }
    }
};
matrix mutl(matrix a, matrix b)		//矩阵乘法
{
    matrix fin;
    memset(fin.m,0,sizeof(fin.m));
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            for(int k=0;k<4;k++){
                fin.m[i][j] += a.m[i][k]*b.m[k][j];
            }
            fin.m[i][j] %= mod;   //1  模余
        }
    }
    return fin;
}
matrix mypow(matrix temp,long long n)		//快速幂
{
    matrix ans;
    ans.ini();
    while(n!=0){
        if(n&1) ans = mutl(ans,temp);
        temp = mutl(temp,temp);
        n >>= 1;

    }
    return ans;
}
int main()
{
    long long  n;
    matrix temp;		//构造temp矩阵
    temp.ini();
    temp.m[0][1] = 1;
    temp.m[0][2] = 1;
    temp.m[1][0] = 1;
    temp.m[1][1] = 0;
    temp.m[2][3] = 1;
    int res[4] = {1,1,3,1};	//beg不用构造为矩阵,数组就可以。
    while(cin >> n){
        if(n>2){
            long long suma = 0;
            matrix en = mypow(temp,n-2);    //让temp矩阵不断乘。注意是(n-2)次
            for(int i=0;i<4;i++){
                suma += ( (en.m[0][i]%mod)*(res[i]%mod) )%mod;//2  取余,同余定理
            }
            suma %= mod;    //3   结果再取余
            cout << suma << endl;
        }
        else cout << 1 <<endl;
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值