51nod 1365 Fib(N) mod Fib(K)
个人评价:考一些奇奇怪怪的知识点呢
算法
矩阵快速幂、斐波那契公式
题面
求\(F_n\%F_k\)的值,\(1\leq n,k\leq 1e18\)
问题分析
我一开始居然想着直接矩阵快速幂求出两个值算,我也是真的牛……
我们要知道这些斐波那契公式(考的真怪)
\[F_{-n}=(-1)^{n-1}F_n \]\[F_n=F_kF_{n-k+1}+F_{k-1}F_{n-k} \]\[F_{k-1}^2+F_{k-1}F_k-F_k^2=(-1)^k \]问题求的是\(F_n \% F_k\)的值,所以我们考虑所有计算推导相等在模\(F_k\)下进行
开始娱乐地推式子了
\[\begin{aligned} F_n&=F_kF_{n-k+1}+F_{k-1}F_{n-k} \\ &=F_{k-1}F_{n-k}\\ &=F_{k-1}(F_kF_{n-2k+1}+F_{k-1}F_{n-2k})\\ &=F_{k-1}^2F_{n-2k}\\ \end{aligned} \]所以可以得到\(F_n=F_{k-1}^{\lfloor\frac{n}{k}\rfloor}F_{n\%k}\)
看到最后一个公式,我们也在模\(F_k\)意义下推导
\[\begin{aligned} (-1)^k&=F_{k-1}^2+F_{k-1}F_k-F_k^2 \\ &=F_{k-1}^2\\ \end{aligned} \]令\(\lfloor\frac{n}{k}\rfloor=i,n\%k=j\) 考虑将这个带入到\(F_n\)的式子,然后进行分类讨论:
- 当i&1=0:\(F_n=(-1)^{k\times \frac{i}{2}}F_j\)
- 当i&1=1:\(F_n=F_{k-1}^iF_j=F_{k-1}^i(F_{k-1}F_{j-k}+F_kF_{j-k+1})=F_{k-1}^{i+1}F_{j-k}=(-1)^{\frac{i+1}{2}k+k-j-1}F_{k-j}\)
代码实现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll p=1e9+7;
struct Matrix{
ll x[10][10];
};
Matrix mul(Matrix a,Matrix b){
Matrix res;
memset(res.x,0,sizeof res.x);
for(ll i=0;i<2;i++){
for(ll j=0;j<2;j++){
for(ll k=0;k<2;k++){
res.x[i][j]=(res.x[i][j]+a.x[i][k]*b.x[k][j]%p)%p;
}
}
}
return res;
}
ll qpow(Matrix a,ll k){
Matrix res;
memset(res.x,0,sizeof res.x);
for(ll i=0;i<2;i++)res.x[i][i]=1;
while(k){
if(k&1)res=mul(res,a);
a=mul(a,a);
k>>=1;
}
return res.x[0][0]%p;
}
void solve(){
ll n,k;
Matrix a;
memset(a.x,0,sizeof a.x);
a.x[0][0]=a.x[0][1]=a.x[1][0]=1;
scanf("%lld%lld",&n,&k);
ll i=n/k,j=n%k;
ll ans=0,mod=qpow(a,k-1);
if(i%2==0){
if(j==k)ans=0;
else ans=qpow(a,j-1);
if(k%2==1)ans=-ans;
if(ans<0)ans=(ans+mod);
ans=(ans+p)%p;
}else{
if(j==0)ans=0;
else ans=qpow(a,k-j-1);
if((k-j-1)%2==1)ans=-ans;
if(ans<0)ans=(ans+mod);
ans=(ans+p)%p;
}
printf("%lld\n",(ans+p)%p);
}
int main(){
ll T;
scanf("%lld",&T);
while(T--)solve();
return 0;
}
总结
这个考的东西真的很奇怪,也算是我的积累问题吧,毕竟斐波那契我就只知道那两个通项公式,还是得多做点题
标签:res,Matrix,51nod,题解,ll,Fib,ans,mod From: https://www.cnblogs.com/Zhangrx-/p/17380108.html