FRS2 - Fibonaccibonacci(简单)
狮子座想玩一些非常大的数字,好吧......
设FIB斐波那契函数:
FIB(0)= 0; FIB(1)= 1
和
对于N> = 2 FIB(N)= FIB(N-1)+ FIB(N-2)
实施例:我们有FIB(6)= 8,和FIB(8)= 21,所以FIB(FIB(6))= 21
输入
输入以单行中的测试用例数T开头。
在下一个T行的每一行中,存在整数N.
输出
对于每个测试用例,打印FIB(FIB(N)),
给出你的答案模1000000007。
链接原题
https://www.spoj.com/problems/FRS2/
此题的关键就在求f(n)的循环节
贴上AC代码,代码中有解释。
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#define p 1000000007
#define mod1 2000000016
#define mod2 329616
#define MAXN 1010
using namespace std;
//定义结构体,就是矩阵
struct node{
long long j[2][2];
}k,temp;
//读入,并且对329616求余
long long read(){
char s[MAXN];
scanf("%s",s);
long long tmp=0;
for(int i=0;i<strlen(s);++i){
tmp=(tmp*10+s[i]-'0')%mod2;
}
return tmp;
}
//重载运算符,矩阵相乘
node operator *(node x1,node y1){
node lx;
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
lx.j[i][j]=0;
}
}
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
for(int ll=0;ll<2;++ll){
lx.j[i][j]=(lx.j[i][j]+(x1.j[i][ll]*y1.j[ll][j])%mod1)%mod1;
}
}
}
return lx;
}
//再次重载。。。。。。
//发现前后两次求余的数不同,有重载了一次
//不想再写个函数了,就直接抄了一下
node operator -(node x1,node y1){
node lx;
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
lx.j[i][j]=0;
}
}
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
for(int ll=0;ll<2;++ll){
lx.j[i][j]=(lx.j[i][j]+(x1.j[i][ll]*y1.j[ll][j])%p)%p;
}
}
}
return lx;
}
int main(){
//freopen("Fibonaccibonacci.in","r",stdin);
//freopen("Fibonaccibonacci.out","w",stdout);
//此处是测试用的,为了求出f(n)(就是斐波那契数列)对p求余的循环节mod1
//然后再次求出对mod1求余的循环节mod2,简化运算
//最后的答案就是f[f[n % mod2] % mod1] % p
/*long long a,b,time1=0;
a=0,b=1;
while(1){
++time1;
long long tmp=(a+b)%mod1;
a=b;
b=tmp;
if(a==0&&b==1){
printf("%d",time1);
break;
}
}*/
long long n,T;
scanf("%lld",&T);
for(int ba=1;ba<=T;++ba){
long long x=read();
k.j[0][0]=1;k.j[0][1]=1;
k.j[1][0]=1;k.j[1][1]=0;
temp.j[0][0]=1;temp.j[0][1]=0;
temp.j[1][0]=0;temp.j[1][1]=1;
//第一次快速幂,求f[n % mod2] % mod1的值
while(x){
if(x%2){
temp=temp*k;
}
k=k*k;
x/=2;
}
long long re=temp.j[0][1];
k.j[0][0]=1;k.j[0][1]=1;
k.j[1][0]=1;k.j[1][1]=0;
temp.j[0][0]=1;temp.j[0][1]=0;
temp.j[1][0]=0;temp.j[1][1]=1;
//第二次快速幂,求f[f[n % mod2] % mod1] % p的值,也就是答案
while(re){
if(re%2){
temp=temp-k;
}
k=k-k;
re/=2;
}
printf("%lld\n",temp.j[0][1]);
}
return 0;
}