题目大意:把n拆分成一些斐波那契数和的形式,要求不同的方案中不能有相同的斐波那契数,求方案数
题解:由于斐波那契数增长较快,int范围内只有不到50项,感觉可以暴力,但是不知道怎么暴……
贪心的用最大的数将n分解,用p[]记录分解的方案
每个斐波那契数都可以用它之前的两个数替换
f[i][1/0]表示选/不选贪心得到的第i个斐波那契数的方案。
f[i][1]=f[i−1][0]+f[i−1][1]
p[i]−p[i−1]表示中间的空位数(即p[i−1],p[i−1]+1…p[i]−1),可以分裂的方案数是空位数/2,如果选了p[i−1]空位数要减去1
f[i][0]=f[i−1][0]∗((p[i]−p[i−1])/2)+f[i−1][1]∗((p[i]−p[i−1]−1)/2)
f[1][1]=1,f[1][0]=(pos[1]−1)/2
我的收获:reverse函数……神奇dp
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M=105;
#define ll long long
int tot,pos[M];
ll n,fib[M];
ll f[M][M];
void DP()
{
f[1][1]=1,f[1][0]=(pos[1]-1)/2;
for(int i=2;i<=tot;i++){
f[i][1]=f[i-1][0]+f[i-1][1];
f[i][0]=f[i-1][0]*((pos[i]-pos[i-1])>>1)+f[i-1][1]*((pos[i]-pos[i-1]-1)>>1);
}
}
void work()
{
DP();
printf("%lld\n",f[tot][0]+f[tot][1]);
}
void init()
{
fib[1]=1;fib[2]=2;
for(int i=3;i<=88;i++) fib[i]=fib[i-1]+fib[i-2];
cin>>n;
for(int i=88;i>=1;i--) if(n>=fib[i]) pos[++tot]=i,n-=fib[i];
reverse(pos+1,pos+tot+1);
}
int main()
{
init();
work();
return 0;
}
本文介绍了一种利用斐波那契数列解决整数拆分问题的方法,并通过动态规划实现。具体讨论了如何将一个整数n拆分为若干不同的斐波那契数之和,以及计算所有可能的不同拆分方案的数量。
8726

被折叠的 条评论
为什么被折叠?



