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

 

posted @   蒟蒻JHY  阅读(263)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示