• Evanyou Blog 彩带


      题目传送门

      转载自:five20,转载请注明出处

      本来看到这题,蒟蒻是真心没有把握的,还是five20大佬巨orz

      首先由于斐波拉契数的前两项是1,1 ,所以易得对于任何整数必能写成多个斐波拉契数加减的形式。

      对于一个数x ,我们贪心找到与x 差值最小的斐波拉契数,将新的x 赋为差值,每次进行这个操作,统计次数,直到x 为0 为止,输出次数。

      证明上述过程也很简单:由于我们知道任何整数必能写成多个斐波拉契数加减的形式,所以我们显然使xx 每次变得越小越好(即减的越多越好),因为每个斐波拉契数都等于前面两项的和,所以我们完全没必要将一步操作改为两步操作。

      举个例子:当n=8 ,答案是1 (即8=8 ,8 为第6项),而我们不需要将前面的3,5 什么的记录进去,因为这样会多1 步操作。当n=11 ,答案是2 (即11=8+3 或11=132 ),显然不用将8 拆为更小的斐波拉契数之和,也不用将13 拆为更小的斐波拉契数之和,这样必然会徒增次数。

      那么具体实现时,直接预处理斐波拉契数,然后对于每次询问,二分出第一个大于等于该值的位置p ,然后第一个小于该值的值位置p1 ,则x=min(f[p]x,xf[p1]) 。

      Code:

      

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<iomanip>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int n,tot;
    ll m,f[93];
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n;
      f[0]=f[1]=1;
      for(int i=2;i<=91;i++)
        f[i]=f[i-1]+f[i-2];
      for(int t=1;t<=n;t++){
        cin>>m;tot=0;
        while(m){
          ll p=lower_bound(f,f+92,m)-f;
          ll q=p-1;
          m=min(m-f[q],f[p]-m);
          tot++;}
        cout<<tot<<endl;
      }
      return 0;
    }
  • 相关阅读:
    字符菱形
    字符三角形
    10:超级玛丽游戏
    09:字符菱形
    08:字符三角形
    07:输出浮点数
    06:空格分隔输出
    05:输出保留12位小数的浮点数
    04:输出保留3位小数的浮点数
    02:输出第二个整数
  • 原文地址:https://www.cnblogs.com/cytus/p/8823157.html
Copyright © 2020-2023  润新知