Pro
设f(x)f(x)表示斐波那契数列的第x项。求f(f(x))f(f(x))对1e9+71e9+7取模的答案。其中x≤10100x≤10100。
Sol
本题的代码实现真的不难,难就难在了思路和预处理。
分析:我们令t=f(x)t=f(x),那么题目转化为求f(t)f(t)对1e9+71e9+7取模的值。考虑取模,取模后肯定会产生一个类似循环节的东西,所以求f(t)f(t)对1e9+71e9+7取模的值的循环节,记为T1T1。求出来之后再返回去,求f(x)f(x)的循环节,记为T2T2,f(x)≤T1f(x)≤T1,此时应取模T1T1求得T2T2。最后问题转化为:求f(f(xf(f(x的值。因为xx的范围很大,所以考虑高精度取模。
预处理:其实需要预处理的只是和T2T2,因为由题目可知,T1T1和T2T2为常数(不随xx变化而变化)。
下面代码是矩阵快速幂的斐波那契数列(一次操作)。
Code
#include<iostream>
#include<cstdio>
#include<set>
#include<string>
#define LL long long
using namespace std;
struct Ju1 {
LL x , y;
};
struct Ju2 {
LL x1 , x2 , x3 , x4;
};
const LL mod = 1e9+7;
LL T1 = 2000000016 , T2 = 32916;
string n;
Ju1 dw1;
Ju2 dw2 , dw3;
Ju2 mul(Ju2 x , Ju2 y) {
Ju2 t;
t.x1 = (x.x1 * y.x1 % mod + x.x2 * y.x3 % mod) % mod;
t.x2 = (x.x1 * y.x2 % mod + x.x2 * y.x4 % mod) % mod;
t.x3 = (x.x3 * y.x1 % mod + x.x4 * y.x3 % mod) % mod;
t.x4 = (x.x3 * y.x2 % mod + x.x4 * y.x4 % mod) % mod;
return t;
}
Ju1 qmul(Ju2 x , Ju1 y) {
Ju1 t;
t.x = (x.x1 * y.x % mod + x.x2 * y.y % mod) % mod;
t.y = (x.x3 * y.x % mod + x.x4 * y.y % mod) % mod;
return t;
}
Ju2 qpow(Ju2 x , int y) {
if(y == 0)
return dw3;
Ju2 t = qpow(x , y/2);
if(y%2 == 0)
return mul(t , t);
return mul(mul(t , t) , dw2);
}
LL fib(LL x) {
if(x == 1)
return 1;
Ju1 t = qmul(qpow(dw2,x-2) , dw1);
return t.x % mod;
}
void init() {
dw1.x = 1 , dw1.y = 1;
dw2.x1 = dw2.x2 = dw2.x3 = 1 , dw2.x4 = 0;
dw3.x1 = dw3.x4 = 1 , dw3.x2 = dw3.x3 = 0;
}
LL qmod(string s , LL x) {
LL d = 0;
for(int i=0; i<s.size(); i++)
d = (d*10 + (s[i]-'0'))%x;
return d;
}
int main() {
cin>>n;
init();
printf("%lld",fib(fib(qmod(n,T2))%T1)%mod);
return 0;
}