zoukankan      html  css  js  c++  java
  • Interesting Integers

    给你一个k,k是一个斐波那契数列的某一项,要你求出对应斐波那契数列的第1项a和第2项b,且a<=b,并且b在·所有情况下最小,a在b最小的情况下最小。

     

    先讲一个斐波那契的特殊性质:

    a3=b1*a1+b2*a2

    a4=b2*a1+b3*a2

    a5=b3*a1+b4*a2

    a6=b4*a1+b5*a2

    斐波那契数列可以这样写,所以每一项都可以认为是为由若干个a1和a2按一定比例相加得来,如果对数学稍微敏感一点,马上就可以看出系数b的值:

    b1=1,b2=1,b3=2,b4=3,b5=5

    由此发现决定a1a2比例的系数b实际上也是斐波那契数列

    所以问题可以转化为:

    k=bx-1*a1+bx*a2的整数解(k为题目给出数,a1为a,a2为b)

    这个式子看上去很像扩展欧几里得的式子,但是是不能用扩欧求解的,因为斐波那契数列邻项互质。(有兴趣可以自行推导)

    所以我们对a2赋值从小到大求解即可。(因为第一要求是a2最小)

    那么还有一个问题:

    我们的系数第x项是如何确定的?

    假设k=bx-1*a1+bx*a2我们已经遍历出答案了,a1a2为已知数,如果我们把系数下调会发生什么?

    这里把bx拆分成bx-1和bx-2即可:

    k=bx-2*a2+bx-1*(a1+a2)

    很明显,a和b的值都变大了,所以可以得出结论:x越大越好,所以x值是递减遍历

    代码这样写是因为写的时候是用的这个方程:

    k-(a2-a1)*bx=a1(bx-1+bx)

    附上代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<vector>
    #include<queue>
    #include<set>
    #include<iomanip>
    #include<cctype> 
    #include<stack>
    using namespace std;
    const int MAXN=3e5+5;
    const int INF=1<<30;
    const long long mod=1e9+7;
    const double eps=1e-8;
    #define ll long long
    #define edl putchar('
    ')
    #define sscc ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define ROF(i,a,b) for(int i=a;i>=b;i--)
    #define FORLL(i,a,b) for(ll i=a;i<=b;i++)
    #define ROFLL(i,a,b) for(ll i=a;i>=b;i--)
    #define mst(a) memset(a,0,sizeof(a))
    #define mstn(a,n) memset(a,n,sizeof(a))
    #define zero(x)(((x)>0?(x):-(x))<eps)
    int a[50],mina,minb,T,n,k,x,y;
    
    int main()
    {
    	a[1]=1,a[2]=1;
    	FOR(i,3,45)
    	a[i]=a[i-1]+a[i-2];
    	cin>>T;
    	while(T--)
    	{
    		minb=mina=mod;
    		cin>>n;
    		ROF(i,44,2)
    		{
    			x=0;
    			int m=n,k=a[i]+a[i-1];
    			while(m>0)
    			{
    				if(m%k==0)
    				{
    					mina=m/k,minb=mina+x;
    					break;
    				}
    				m-=a[i];
    				x++;
    			}
    			if(mina!=mod&&minb!=mod)
    			{
    				break;
    			}
    		}
    		cout<<mina<<" "<<minb<<endl;
    	}
    }
    

      

  • 相关阅读:
    用于主题检测的临时日志(594fb726-af0b-400d-b647-8b1d1b477d72
    返璞归真vc++之字符类型
    DIV居中
    程序员职业生涯
    枚举进程句柄
    不使用mutex设计模式解决并发访问cache
    服务器权重分配算法
    xmemecached中的一致性hash算法
    安卓课堂练习
    pythonPTA---分支循环与集合7-1 jmu-python-韩信点兵 (20分) 7-2 打印数字矩形 (10分) 7-3 成绩统计 (10分) 7-4 找列表中最大元素的下标 7-5 删除列表中的重复值
  • 原文地址:https://www.cnblogs.com/qq936584671/p/9295193.html
Copyright © 2011-2022 走看看