题目
自己确定G1和G2,
G3=G1+G2,G4=G2+G3,
G[i]=G[i-1]+G[i-2],
对于给定n,如果n出现在这个数列中
求最小的G2,使得G1<=G2
输出G1和G2
思路来源
https://blog.youkuaiyun.com/Originum/article/details/81393168
题解
G1=a+0b,G2=0a+b,G3=a+b,G4=a+2b,G5=2a+3b
注意到它们的系数是在F数列中1 0 1 1 2 3 5 8出现的
Gi的a的系数是F[i-1],b的系数F[i],
而F序列后面是斐波那契数列
所以就递增扫F序列,判断F[i]x+F[i+1]y==n能否成立
先扩展欧几里得,由于令a<=b且b最小,
所以就是求x<=y的最小y,注意到y减小则x增大,
故y与x最接近,即下一步y减小x会反超
求出一组特解x,y后,令x和y最接近且x<=y的步骤如下

由于C++int除以int是近零取整,-2.5取整会被搞成-2,但是-3才符合条件
所以,如果这个值小于0且不能被整除,k--
然后x+=k*b/d,y-=k*a/d就是答案
心得
感觉思维题做的还是不够多,不知变通
这题根本看不出来是扩展欧几里得啊
还有算是知道了extgcd的一些小应用叭
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=46;
int t,f[maxn]={1,0};//系数矩阵
ll c;
ll a,b,x,y,ansx,ansy;
ll extgcd(ll a,ll b,ll &x,ll &y)
{
ll d=a;
if(b)d=extgcd(b,a%b,y,x),y-=(a/b)*x;
else x=1,y=0;
return d;
}
int main()
{
for(int i=2;i<maxn;++i)
f[i]=f[i-1]+f[i-2];
scanf("%d",&t);
while(t--)
{
scanf("%lld",&c);
ansx=ansy=1e18;
for(int i=0;i<maxn-1;++i)
{
a=f[i];b=f[i+1];
//printf("%lld %lld\n",a,b);
ll d=extgcd(a,b,x,y);
if(c%d)continue;
x*=(c/d);y*=(c/d);
a/=d;b/=d;
ll k=(y-x)/(a+b);
if(x>y&&(y-x)%(a+b))k--;//近零取整,负的得-1
x+=k*b,y-=k*a;
if(x>0&&y>0&&y<ansy)
ansx=x,ansy=y;
}
printf("%lld %lld\n",ansx,ansy);
}
return 0;
}
本文探讨了一种数列求解问题,通过解析数列规律与斐波那契数列的联系,引入扩展欧几里得算法解决特定条件下的数列求解。文章详细解释了算法实现过程,包括如何利用扩展欧几里得算法找到满足条件的最小值,并通过代码示例展示了完整的解决方案。
671

被折叠的 条评论
为什么被折叠?



