同样的历史遗留。 问有多少种方案可以把该数分解成若干彼此不同的斐波那契数之和。
思路是参考vv的。
做完这些,还有两道vv的 插头dp和背包。只能有缘机会在搞了。
code :
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
typedef unsigned long long uLL;
const uLL maxn = (uLL)1e18 + 10;
uLL a[100005];
uLL dp[100005][2];
map<uLL,int> mp;
int sum;
void init() {
a[1] = 1; a[2] = 2;
mp[1] = 1; mp[2] = 2;
for(int i = 3; ; i++) {
a[i] = a[i - 1] + a[i - 2];
mp[a[i]] = i;
if(a[i] >= maxn) {
sum = i;
break;
}
}
}
int main(void) {
init();
int n;
cin >> n;
while(n--) {
uLL t;
cin >> t;
vector<uLL> v;
while(t != 0) {
int x = lower_bound(a, a + sum, t) - a;
if(t != a[x]) x--;
v.push_back(a[x]);
t = t - a[x];
}
sort(v.begin(), v.end());
dp[0][0] = 1;
dp[0][1] =(mp[v[0]] - 1) / 2;
int m = (int)v.size() - 1;
for(int i = 1; i <= m; i++) {
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
uLL case1 = (mp[v[i]] - mp[v[i - 1]] - 1) / 2 * dp[i - 1][0];
uLL case2 = (mp[v[i]] - mp[v[i-1]]) / 2 * dp[i - 1][1];
dp[i][1] = case1 + case2;
}
cout << dp[m][0] + dp[m][1] << endl;
}
return 0;
}