[BZOJ] 2660 [Beijing wc2012]最多的方案

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 670  Solved: 387
[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

Source

好題,很有意思。

第一反應是斐波那契數在1e18內不多,從大到小,貪心地選數。一個數能選的話,後面也一定能選,但不一定有第一處優,所以能選就選。

這樣的構造是唯一的。

然後就是問題了, 對於這樣的一個序列,任何一項a[i]都可以被a[i-1]和a[i-2]替代,需要求替代的方案數,也就是答案了。

這裏卡住了,dp的威力就在此了。

f[i][0/1]表示a序列第i個數不替換/替換的方案數
f[i][1]=f[i-1][0]+f[i-1][1]
f[i][0]=f[i-1][0] * ((a[i]-a[i-1])/2)+f[i-1][1] * ((a[i]-a[i-1]-1)/2)

記得開longlong

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;

const int MAXN=1005;

ll f[MAXN][2],fib[MAXN],n;
ll a[MAXN],p;

const int TOP=88;
int main(){
    fib[1]=1;fib[2]=2;
    for(int i=3;i<=TOP;i++) fib[i]=fib[i-1]+fib[i-2];
    cin>>n;
    ll sav=n;//
    for(int i=TOP;i>=1;i--){
        if(!sav) break;
        if(sav>=fib[i]) {
            a[++p]=i;
            sav-=fib[i];
        }
    }
    if(sav) return cout<<0,0;
    sort(a+1,a+1+p);
    f[1][1]=1;
    f[1][0]=(a[1]-1)/2;
    for(int i=2;i<=p;i++){
        f[i][1]=f[i-1][0]+f[i-1][1];
        f[i][0]=f[i-1][0]*((a[i]-a[i-1])/2)+f[i-1][1]*((a[i]-a[i-1]-1)/2);
    }
    cout<<f[p][0]+f[p][1];
    return 0;
}
發佈了180 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章