好题。
fib
数不多,先都直接得到。注意到
fib
相邻数可以合并,所以我们就贪心的求出数最大的一组解,然后考虑把取来的数分裂。
设我们现在有一个
fibi
,他能分裂成什么样呢?
fibi=fibi−1+fibi−2=fibi−1+fibi−3+fibi−4=fibi−1+fibi−3+fibi−5+fibi−6
注意到分裂会占去之前的一段连续空间,且能分裂的次数为 允许的空间/2 。
所以就可以直接 DP 了, fi,1/0 表示最大解中前 i 个斐波那契数,1/0是
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
LL n,fib[105],f[105][2],a[105];
int main(){
freopen("bzoj2660.in","r",stdin);
freopen("bzoj2660.out","w",stdout);
scanf("%lld",&n);
fib[1]=1; fib[2]=2;
for(int i=3;i<=88;i++) fib[i]=fib[i-1]+fib[i-2];
for(int i=88;i>=1;i--) if(n>=fib[i]) a[++a[0]]=i, n-=fib[i];
if(n) return printf("0"),0;
sort(a+1,a+1+a[0]);
f[1][1]=1; f[1][0]=(a[1]-1)/2;
for(int i=2;i<=a[0];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);
}
printf("%lld\n",f[a[0]][0]+f[a[0]][1]);
return 0;
}