思路
当我刚开始看到这个题的时候,还没有什么思路,但是当我列出了几个关于 (a,b,k) 的式子:
[a+b=k\a+2b=k\2a+3b=k\3a+5b=k\dots
]
可能还不太明显,仔细观察 (a,b) 的系数,可以发现,这不就是斐波那契数列吗!!!
那么我们设 (f(x)) 为斐波那契数列的第 (x) 项,那么可以转化为:
[f(0)*a+f(1)*b=k\f(1)*a+f(2)*b=k
\f(2)*a+f(3)*b=k\dots\f(x-1)*a+f(x)*b=k
]
那么我们就可以枚举 (x) 。
然后,移项,可得:
[b=dfrac{k-f(x-1)*a}{f(x)}
]
由于 (b) 为整数,所以相当于求多少 (a) 可以使得 (f(x)|k-f(x-1)*a) 成立,即:
[k-f(x-1)*aequiv 0~(mod~f(x))\f(x-1)*aequiv k~(mod~f(x))\aequiv k*inv(f(x-1))~ (mod~f(x))
]
由于 (f(x)) 和 (f(x-1)) 互质(这里就不证明了),可以直接扩欧干上去求逆元,然后差不多了
(小trick:因为 (k-f(x-1)*a>0) 即 (a<dfrac{k}{f(x-1)}),所以可以枚举的更少了)
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=45;
const int n=40+2;
const int mod=1000000007;
ll f[N],K,ans;
ll exgcd(ll A,ll B,ll &x,ll &y)
{
if(B==0)
{
x=1,y=0;
return A;
}
ll temp=exgcd(B,A%B,x,y),z=x;
x=y,y=z-(A/B)*y;
return temp;
}
ll inv(ll A,ll POI)
{
ll t,tt;
exgcd(A,POI,t,tt);
return (t%POI+POI)%POI;
}
int main()
{
scanf("%lld",&K);
f[1]=f[2]=1;
for(int i=3;i<=n;i++)
f[i]=f[i-1]+f[i-2];
for(int i=2;i<=n;i++)
{
ll a=(K*inv(f[i-1],f[i]))%f[i],to=K/f[i-1]-1;
if(a<to)
{
if(a==0) ans--;
ans=(ans+1+(to-a)/f[i])%mod;
}
}
printf("%lld",ans);
return 0;
}