买蛋糕

题目描述

野猫过生日,大家当然会送礼物了(咳咳,没送礼物的同志注意了哈!!),由于不知道送什么好,又考虑到实用性等其他问题,大家决定合伙给野猫买一个生日蛋糕。大家不知道最后要买的蛋糕的准确价格,而只会给蛋糕估价,即要买一个不超过多少钱的蛋糕。众 OIer 借此发挥:能否用最少的钱币数去凑成估价范围内的所有价值,使得不管蛋糕价值多少,都不用找钱……

现在问题由此引出:对于一个给定的 \(n\),能否用最少的不等的正整数去组成 \(n\) 以内(包括 \(n\))的所有的正整数呢?如果能,最少需要多少个正整数,用最少个数又有多少不同的组成方法呢?

输入格式

只有一行包含一个整数 \(n\ (1\le n\le 1000)\)

输出格式

一行两个数,第一个数是最少需要多少个数,第二个数是用最少个数的组成方案个数。两个答案用空格分隔。

6

3 2

提示

最少用三个数,有两种方法,分别是:\(1,2,3\)\(1,2,4\)

  • 对于 \(1,2,3\)\(1,2,3\)\(1+3\)\(2+3\)\(1+2+3\)
  • 对于 \(1,2,4\)\(1\)\(2\)\(1+2\)\(4\)\(1+4\)\(2+4\)
#include<bits/stdc++.h>
using namespace std;
int n;
int ans;
int ans1;
void dfs(int last,int sum,int cnt)//每个数的取值范围:[last+1,sum+1],上一个数是last,可以凑出1~sum的值,当前是第cnt个数
{
	//值要<=sum+1,否则凑不出sum+1,要>=last+1否则个数就会超过ans
	//求出后就可以凑出1~sum+x的数了
	//在最后一个数时,数的左边界应该是max(n-sum,last+1)因为还要确保达到n
	if(cnt == ans)
	{
		if(sum+sum+1>=n)//当前在最后一个数,sum+此数最大值可以到达n,才去统计答案
		{
			ans1+=sum+1-max(n-sum,last+1)+1;//统计答案
		}
		return ;
	}
	for(int i=last+1;i<=sum+1;i++)
	{
		dfs(i,sum+i,cnt+1);
	}
}
signed main()
{	
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n;
	for(int x=1;x<=n;x*=2,ans++);
	cout<<ans<<' ';
	dfs(0,0,1);
	cout<<ans1<<'\n';
	return 0;
}
posted @ 2025-07-14 15:52  ltl0825  阅读(15)  评论(0)    收藏  举报