• Contest20140906 ProblemC 菲波拉契数制 DP



    C.菲波拉契数制
    时间:2s   内存:65536KB
    我们定义如下数列为菲波拉契数列:
                        F (1) = 1
                        F (2) = 2
                        F (i) = F(i-1)+F(i-2) (i>=3)
    给定任意一个数,我们可以把它表示成若干不同的菲波拉契数之和。比如13有三种表示法
    13=13
    13=5+8
    13=2+3+8
    现在给你一个数n,请输出把它表示成若干不同的菲波拉契数之和有多少种表示法。

    输入:
    第一样一个数T,表示数据组数,之后T行,每行一个数n。
    20%的数据:T<=10,n<=30
    60%的数据:T<=100,n<=100000
    100%的数据:T<=10^5, n<=10^18

    输出:
    输出T行,每行一个数,即n有多少种表示法。

    样例:

    输入:
    6
    1
    2
    3
    4
    5
    13

    输出:
    1
    1
    2
    1
    2
    3

    这种DP很不容易看出想出状态,我在考试的时候大部分时间都用在这道题上了,评讲时也证明我基本上已经想了90%的正解,只有一个我没有想到,即最大表示后每一项后移步数不超过1。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<string>
    #include<queue>
    #include<stack>
    using namespace std;
    #ifdef WIN32
    #define LL "%I64d"
    #else
    #define LL "%lld"
    #endif
    typedef long long qword;
    typedef long long number;
    #define MAXF 110
    #define MAXN 110000
    #define PROB "C"
    qword fib[MAXF];
    int topf;
    vector<int> vec;
    void init()
    {
            int i;
            fib[0]=fib[1]=1;
            for (i=2;fib[i-1]<1000000000000000000LL;i++)
            {
                    fib[i]=fib[i-1]+fib[i-2];
            }
            topf=i-1;
    }
    qword f[MAXF][2];
    int a[MAXF];
    qword n,m;
    int main()
    {
            //freopen("input.txt","r",stdin);
            //freopen("output.txt","w",stdout);
            freopen(PROB".in","r",stdin);
            freopen(PROB".out","w",stdout);
            int i,j,k;
            int x,y,z;
            int nn;
            scanf("%d",&nn);
            init();
            while (nn--)
            {
                    scanf(LL ,&n);
                    vec.clear();
                    for (i=topf;i>0;i--)
                    {
                            if (fib[i]<=n)
                            {
                                    n-=fib[i];
                                    vec.push_back(i);
                            }
                    }
                    sort(vec.begin(),vec.end());
                    for (i=0;i<vec.size();i++)
                    {
                            a[i]=(-((i)?vec[i-1]:1)+vec[i]);
                    }
                    f[0][1]=1;
                    f[0][0]=a[0]/2;
                    for (i=1;i<vec.size();i++)
                    {
                            f[i][0]=((a[i]-1)/2)*f[i-1][1]+((a[i])/2)*f[i-1][0];
                            f[i][1]=f[i-1][0]+f[i-1][1];
                    }
                    printf("%lld
    ",f[vec.size()-1][0]+f[vec.size()-1][1]);
            }
            return 0;
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    学习九-python 异常处理
    验证基于逻辑回归的隐马尔可夫模型的心音信号切分算法(literature study)
    字典的内置方法比较
    学习六
    Ubuntu 16.04 LTS 搜狗输入法安装
    集合经验模态分解(EEMD)在语音中的应用举例
    SwfUpload及imgareaselect使用方法
    Uploadify插件使用方法
    Ueditor使用方法
    PartialView 加载Js
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3960863.html
Copyright © 2020-2023  润新知