码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2660: [Beijing wc2012]最多的方案

时间:2018-01-11 20:36:25      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:discus   bzoj   enter   lin   lan   16px   can   inpu   答案   

                   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\n",dp(i-1,n));
    return 0;
}

 

bzoj 2660: [Beijing wc2012]最多的方案

标签:discus   bzoj   enter   lin   lan   16px   can   inpu   答案   

原文地址:https://www.cnblogs.com/JYYHH/p/8270032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!