Fib(N) mod Fib(K)
Fib(N)表示斐波那契数列的第N项( F(0)=0,F(1)=1),给出N和K,求 Fib(N)modFib(K)。由于结果太大,输出 Mod 1000000007 的结果。
正解部分
首先要知道
Fi=FkFi−k+1+Fk−1Fi−k,
在 mod Fk 意义下继续化简 ↓
Fi=Fk−1Fi−k=Fk−1(FkFi−2k+1+Fk−1Fi−k−k)=Fk−12Fi−2k ⋯=Fk−1⌊ki⌋Fi%k
再要知道
Fk−12+Fk−1Fk−Fk2=(−1)k
证明:
首先要知道 二阶行列式 的相关内容如下.
二阶行列式: det(a bc d)=ad−bc
再看斐波那契数列的转移矩阵如下,
[1 11 0]k=[Fk+1 FkFk Fk−1]
矩阵相等, 行列式也相等,
∴(−1)k=Fk+1Fk−1−Fk2=Fk−12+Fk−1Fk−Fk2
得证 .
所以在 modFk 意义下, (−1)k=Fk−12 .
再看原式: Fi=Fk−1⌊ki⌋Fi%k
设 x=⌊ki⌋, y=i%k,
则 Fi=Fk−1xFy={x&1==0, (−1)2xkFyx&1==1, (−1)(2x+1)kFy−k=(−1)(2x+1)k+k−y−1Fk−y
其中 Fy−k 可能为负数, 这里又要引入
斐波那契的负系数项:F−i=(−1)i−1Fi .
然后就可以 AC 辣 !
总结一下, 该题涉及的知识点有 ↓
- Fi=FkFi−k+1+Fk−1Fi−k
- Fk−12+Fk−1Fk−Fk2=(−1)k
- F−i=(−1)i−1Fi
实现部分
#include<bits/stdc++.h>
#define reg register
typedef long long ll;
const int mod = 1e9 + 7;
ll N;
ll K;
struct Matrix{ int C[4][4]; Matrix(){ memset(C, 0, sizeof C); } };
Matrix modify(const Matrix &a, const Matrix &b){
Matrix s;
for(reg int i = 1; i <= 2; i ++)
for(reg int j = 1; j <= 2; j ++)
for(reg int k = 1; k <= 2; k ++){
int &t = s.C[i][j];
t = (1ll*t + (1ll*a.C[i][k]*b.C[k][j]%mod)) % mod;
}
return s;
}
Matrix ma_Ksm(Matrix a, ll b){
Matrix s;
for(reg int i = 1; i <= 2; i ++) s.C[i][i] = 1;
while(b){
if(b & 1) s = modify(s, a);
a = modify(a, a); b >>= 1;
}
return s;
}
ll get(ll k){
Matrix res, I;
res.C[1][1] = 1;
I.C[1][1] = I.C[1][2] = I.C[2][1] = 1;
I = ma_Ksm(I, k);
res = modify(res, I);
return res.C[1][2];
}
void Work(){
scanf("%lld%lld", &N, &K);
ll x = N/K, y = N%K;
if(x & 1){
x = (x+1)/2, y = K-y-1;
x = (K & 1) * x;
ll Ans = ((x+y&1)?-1:1) * get(y + 1);
if(Ans < 0) Ans = (Ans + get(K) + mod) % mod;
printf("%lld\n", Ans);
}else{
x >>= 1;
if(!(K&1)) x = 0;
ll Ans = ((x&1)?-1:1) * get(y);
if(Ans < 0) Ans = (Ans + get(K) + mod) % mod;
printf("%lld\n", Ans);
}
}
int main(){
freopen("fib.in", "r", stdin);
freopen("fib.out", "w", stdout);
int T; scanf("%d", &T);
while(T --) Work();
return 0;
}