BJOI2012 最多的方案

BJOI2012 最多的方案

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

Solution


有一个数学结论:第i个斐波那契数 拆成别的互不相同的斐波那契数表示,最多有(i-1)/2 种。那么我们用贪心,找出这个给出的数分解成斐波那契数的一个方案,再递推求解。

Code


//Writer : Hsz %WJMZBMR%tourist%hzwer
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
LL p[100],num;
LL n,fi[100],cnt,ans;
void fib(int x) {
	if(fi[x-1]>n) {
		cnt=x-1;
		return;
	}
	fi[x]=fi[x-1]+fi[x-2];

	fib(x+1);
}
LL f[105][2];//第i个fib,拆分/不拆 方案数。
int main() {
	cin>>n;
	fi[0]=fi[1]=1;
	fib(2);
	for(int i=cnt; i; i--) {
		if(n>=fi[i]) n-=fi[i],p[++num]=i;
	}
	sort(p+1,p+1+num);
	f[1][1]=1;f[1][0]=(p[1]-1)/2;
	for(int i=2; i<=num; i++) {
		f[i][1]=f[i-1][1]+f[i-1][0];
		f[i][0]=((p[i]-p[i-1]-1)/2)*f[i-1][1]+((p[i]-p[i-1])/2)*f[i-1][0];//整个表示不能有重复的数。
	}
	cout<<f[num][0]+f[num][1];
	return 0;
}
posted @ 2018-06-04 21:23  SWHsz  阅读(227)  评论(0编辑  收藏  举报