专栏文章

P4133 [BJOI2012] 最多的方案

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miou3j9m
此快照首次捕获于
2025/12/03 01:10
3 个月前
此快照最后确认于
2025/12/03 01:10
3 个月前
查看原文
CPP
#include <iostream>
#include <map>
#define int long long//千万要记得开long long 

using namespace std;

const int N = 88;

int n,f[N + 5],s[N + 5];//注意数组加5,防止越界 
map<pair<int,int>,int> m;//map第一位存还剩多少可以选,二位表示选到第i位了 

int dfs (int x,int now) {//x表示还剩x的数值可以选,now表示当前是第now个斐波那契数 
//	cout << x << ' ';
	if (x < 0) return 0;//如果说还剩得数已经是负数了,代表永远也选不到了,直接返回0,代表方案数是0 
	if (m.count({x,now})) return m[{x,now}];//记忆化搜索,表示map数组里要是有这个数的方案总数的话,直接返回。 
	if (now == 0 && x == 0) return 1; //如果说还剩得数是零,且还能选的数是0,代表必须全部选完才能凑出来,代表方案数是1 
	if (s[now - 1] < x) return m[{x,now}] = dfs (x - f[now],now - 1);//如果说前now - 1个斐波那契数的和都小于要选的数的话,那第now个数必须得选,否则就凑不够x了,不用担心减完会是负数,因为有if语句帮忙兜底 
	if (f[now] > x) return m[{x,now}] = dfs (x,now - 1);//如果说当前的数大于x就不选,往前找,直到能选上为止 
	return m[{x,now}] = dfs (x - f[now],now - 1) + dfs (x,now - 1);//返回选或不选的方案总数之和 
}

signed main () {
	
	cin >> n;
	
	f[0] = f[1] = s[1] = 1;//斐波那契数第一和第二个设为1 
	
	for (int i = 2;i <= N;i ++) {
		f[i] = f[i - 1] + f[i - 2];//从二开始初始化斐波那契 
		s[i] = s[i - 1] + f[i];//s表示前i个斐波那契数的前缀和 
	}
	
//	for (int i = 1;i <= N;i ++) {
//		cout << s[i] << ' ';
//	}
	
	cout << dfs (n,88) << '\n';//dfs,n表示还剩n可以减,88表示当前的斐波那契数 
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...