每日一题:最多的方案
题目链接:https://www.luogu.com.cn/problem/P4133
题目描述:
现在给一个正整数n,它可以写成一些斐波那契数的和的形式。如果我们要求不同的方案中不能有相同的斐波那契数,那么对一个n最多可以写出多少种方案呢?
输入格式:只有整数n.
输出格式:输出组成n的方案数.
解题思路:记录小于等于n的斐波那契数,并用dp数组对其进行分解.
具体代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
////对于n的范围到110的斐波那契数的和是大于1e8的
const int MaxN = 110;
int main()
{ ll n;
vector<ll>f(MaxN);
int m=0,cnt=0;
vector<int>pos(MaxN);
vector<vector<int>>g(MaxN,vector<int>(2));
cin >> n;
////生成斐波拉契数列(仅归纳小于等于n的)
f[1] = 1, f[2] = 2;
for (m = 3; f[m - 1] <= n; ++m)
f[m] = f[m - 1] + f[m - 2];
--m;
////从最大的斐波拉契数开始分解n,并记录能分解的数的位置
for (int i = m; i >= 1; --i)
if (n >= f[i])
{
n -= f[i];
pos[++cnt] = i;
}
std::sort(pos.begin()+1, pos.begin()+cnt+1);
////构建dp数组以及分解大的斐波那契数
g[1][1] = 1, g[1][0] = pos[1] - 1 >> 1;
for (int i = 2; i <= cnt; ++i)
{ g[i][1] = g[i - 1][0] + g[i - 1][1];
g[i][0] = g[i - 1][1] * (pos[i] - pos[i - 1] - 1 >> 1) + g[i - 1][0] * (pos[i] - pos[i - 1] >> 1);
}
printf("%d\n", g[cnt][0] + g[cnt][1]);
return 0;
}