题意
题目链接
求出把$n$分解为斐波那契数的方案数,方案两两不同的定义是分解出来的数不完全相同
Sol
这种题,直接爆搜啊。。。
打表后不难发现$<=1e18$的fib数只有88个
最先想到的应该是直接把$n$加入到搜索状态里,然后枚举能被分成哪些
但是这样分解出来的数可能会有重复的,因此我们还要把当前考虑到第几个数也加入到状态里。
不难得到以下代码
但是很显然会T飞。
优化一下,只考虑当前的fib数对答案的贡献,
也就是搜两种情况:
1、用该数分解
2、不用该数分解
代码是这样的
然而还是会T飞。
继续剪枝。
根据斐波那契的性质$sum_{i = 1}^n f_i = f_{n+2} -1$
因此我们想要用前$ti - 1$个合成$x$,必须满足$x < f_{ti+1}$。
然后就A了qwq
// luogu-judger-enable-o2
#include
#include
#include
#define Pair pair
#define MP(x,y) make_pair(x,y)
#define fi first
#define se second
#define int long long
#define ull unsigned long long
using namespace std;
const int MAXN = 1e5 + 10;
inline int read() {
char c = getchar(); int x = 0,f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
return x * f;
}
int f[MAXN],tot,lim,dp[MAXN],N;
map
int dfs(int x,int ti) {
if(mp.find(MP(x,ti)) != mp.end()) return mp[MP(x,ti)];
if(x == 0) return 1;
int ans = 0;
/*for(int i = ti; i >= 1; i--) {
if(x - f[i] >= 0) ans += dfs(x - f[i],i - 1);
//else break;
}*/
if(x - f[ti] >= 0) ans += dfs(x - f[ti],ti - 1);
if(x < f[ti + 1])
ans += dfs(x,ti - 1);
return mp[MP(x,ti)] = ans;
}
main() {
lim = 1e18;
f[1] = 1; f[2] = 2;
for(int i = 3; i; i++) {
f[i] = f[i - 1] + f[i - 2];
if(f[i] > lim) {tot = i; break;}
}
N = read();
//dp[0] = 1;
cout << dfs(N,tot - 1);
return 0;
}
总结以上是内存溢出为你收集整理的洛谷P4133 [BJOI2012]最多的方案(记忆化搜索)全部内容,希望文章能够帮你解决洛谷P4133 [BJOI2012]最多的方案(记忆化搜索)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)