题目描述
一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。
例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得的多少种不同的幸运的袋子。
输入描述:
第一行输入一个正整数n(n ≤ 1000)
第二行为n个数正整数xi(xi ≤ 1000)
输出描述:
输出可以产生的幸运的袋子数
输入
3
1 1 1
输出
2
说实话,对于牛客网上的编程题,或者其他上边的编程题,我个人来说是很少往递归上面考虑的,因为递归很容易溢出,而且速度慢,多半不能满足要求,但是下面的题目却要使用递归来解决,如果有非递归的解决办法,还请指出。
题目要求 袋子里的数满足 和大于成绩,给出n个数,要求其中有多少个子集满足这样的条件,采用列举法来看下这个问题:
个数 | 方案数、要求 |
2 | 必须有一个数为1,(1,1)、(1,2).....(1,999) |
3 | (1,1,1)、(1,1,2)、....、(1,1,999) |
4 | (1,1,1,1)、(1,1,1,2)、...、(1,1,1,999),(1,1,2,2),(1,1,2,3) |
结论:①假设a1,a2,...ak,如果不满足给定条件,即和sum小于等于积pi,如果此时再选择一个数b,能使其满足sum+b > pi*b,则,b必然为1 ② 袋子中必须有1
所以我们首先进行排序,将输入的数进行有序,才能够进行剪枝,如果sum>p,满足sum+b< pi*b,b和b之后都要剪枝,不用该考虑了
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int *x=NULL;
int count(int pos,int add,long long mul)
{
int num=0;
for(int i=pos;i<n;++i)
{
add+=x[i];
mul*=x[i];
if(add>mul)
num+=1+count(i+1,add,mul);
else if(x[i]==1)
num+=count(i+1,add,mul);
else
break;
add-=x[i];
mul/=x[i];
while(x[i+1]==x[i] && i+1<n)
{
++i;
}
}
return num;
}
int main()
{
cin>>n;
x=new int [n];
int add=0; //和
long long mul=1; //积
for(int i=0;i<n;++i)
{
cin>>x[i];
}
sort(x,x+n);
int num=count(0,add,mul);
cout<<num;
if(x!=NULL)
{
delete []x;
x=NULL;
}
return 0;
}