版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82019289
题目
其中 均为正整数,
问有多少种 ,使得 出现在这个数列里,且不是前两项。
分析
然而可以发现这个其实是ax+by=k的方案数,然而a和b可以通过斐波那契得到,关键是求方案数,那只要求出最小解,剩下就没了,搞搞细节就行了
代码
#include <cstdio>
#define mod 1000000007
using namespace std;
typedef long long ll;
ll f=1,g=0,k,ans;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll max(ll a,ll b){return (a>b)?a:b;}
ll exgcd(ll a,ll b,ll &x,ll &y){//扩展欧几里得
if (!b) {x=1; y=0; return a;}
else {
ll k=exgcd(b,a%b,y,x);
y-=a/b*x; return k;
}
}
ll sum(ll x,ll y){return max(0,x%y?x/y:x/y-1);}
int main(){
scanf("%lld",&k);
for (register int i=1;i<=1000;i++){
g+=f; ll x,y;
if (f>k&&g>k) break;
ll a=f,b=g;
if (k%gcd(a,b)==0){
ll t=k/exgcd(a,b,x,y);
x*=t; y*=t;
if (x<0||y<0){//存在负数
if (x<0) ans=(ans+max(0,sum(y,a)+x/b))%mod;
else ans=(ans+max(0,sum(x,b)+y/a))%mod;
}
else{
if (x&&y) ans=(ans+sum(x,b)+sum(y,a)+1)%mod;
else if (!x) ans=(ans+max(0,sum(y,a)))%mod;
else ans=(ans+max(0,sum(x,b)))%mod;
}
}
f^=g,g^=f,f^=g;
}
return !printf("%lld",ans);
}