zoukankan      html  css  js  c++  java
  • bzoj 2660: [Beijing wc2012]最多的方案

                       Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 617  Solved: 361
    [Submit][Status][Discuss]

    Description

           第二关和很出名的斐波那契数列有关,地球上的OIer都知道:F1=1, F2=2, Fi = Fi-1 + Fi-2,每一项都可以称为斐波那契数。现在给一个正整数N,它可以写成一些斐波那契数的和的形式。如果我们要求不同的方案中不能有相同的斐波那契数,那么对一个N最多可以写出多少种方案呢?

    Input

           只有一个整数N。

    Output

           一个方案数

    Sample Input

    16

    Sample Output

    4

    HINT



    Hint:16=3+13=3+5+8=1+2+13=1+2+5+8

    对于30%的数据,n<=256

    对于100%的数据,n<=10^18


    直接记忆化搜索就行了,fibo(88)就已经>=10^18。
    设g(x,y)为考虑前x个斐波那契数的和为y的方案数。
    答案即为g(87,n)。
    转移的时候可以剪枝:
    1.当y<=f[x]的时候可以转移到g(x-1,y-f[x)。
    2.当y<f[x+1]的时候才可以转移到g(x-1,y)。

    解释一下第二个,因为斐波那契数列有注明前缀和公式 f(1)+f(2)+...+f(x)=f(x+2)-1  (证明可以考虑分
    奇偶添补),所以当y>=f[x+1]的时候,g(x-1,y)一定是0了,不用再转移了。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    map<ll,ll> mmp[105];
    ll n,m,k,f[105];
    
    ll dp(int x,ll lef){
        if(!lef) return 1;
        if(x==2){
            if(lef==1) return 1;
            return 0;
        }
        
        if(mmp[x][lef]) return mmp[x][lef];
        ll ans=0;
        if(lef>=f[x]) ans+=dp(x-1,lef-f[x]);
        if(lef<f[x+1]) ans+=dp(x-1,lef);
        
        mmp[x][lef]=ans;
        return ans;
    }
    
    int main(){
        scanf("%lld",&n);
        f[1]=f[2]=1; int i;
        for(i=3;(f[i]=f[i-1]+f[i-2])<=n;i++);
        
        printf("%lld
    ",dp(i-1,n));
        return 0;
    }
  • 相关阅读:
    【MySQL】悲观锁&乐观锁
    选盘秘籍:用户如何选择SSD/SATA/SAS?
    【MySQL】分页优化
    【MySQL】锁问题最佳实践
    【MySQL】锁入门
    【MySQL】SQL优化系列之 in与range 查询
    【DNS】简单聊聊DNS如何工作
    【MySQL】排序原理与案例分析
    git的使用
    关于fastjson与jackson在反序列化bool型时的区别
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8270032.html
Copyright © 2011-2022 走看看