Description
一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?这个问题难不倒农夫
John
,但当地的农夫
Jack
要有意为难他。刚开始时,
John
养了一对小兔子,
Jack
自第
3
个月起送
John
若干对兔子,假定第
n
个月送
n
对兔子。兔子繁殖后形成新的兔子序列:
Fn = Fn-1 + Fn-2 +n
,(
n>1)
,
F1=1
,
F2 =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;
}
}