聚会(思维)
链接:https://ac.nowcoder.com/acm/contest/37160/E
来源:牛客网
题目描述
一场聚会,每个人都有一个活跃度。一个聚会的活跃度定义为这些人的活跃度组成的可重复数字集合的子集和组成的集合中未出现的最小正整数。现在需要你求出这个聚会的活跃度的值。
输入描述:
第一行一个整数 n (1≤n≤10 5),代表有 n 个人。
第二行 n 个整数,第 i 个数代表第 i 个人的活跃度 ai( 1≤ai≤109 )。
输出描述:
一个整数,输出这个聚会的活跃度值。
示例1
输入
3
1 2 3
输出
7
说明
聚会的集合为{1,2,3} ,子集有{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3},子集的和分别为 0,1,2,3,3,4,5,6,未出现的最小正整数为 7。
备注:
原集合和子集都是可重复数字集合。
思路: 按照题所给思路算肯定是不现实的,所以要另找办法,假设当前满足条件所能凑出来的范围最大值为x,即我们现在能凑成[0,x]中的任意数,当来了一个新元素a, 如果a<=x+1, 区间由[0,x]变为[0,x]并[a,x+a]=[0,x+a] (显然,新元素来后,能凑成的最大正整数一定是x+a,那[a,x+a]中的数是否一定都能凑成呢,新元素来之前,我们已经能凑成[0,x]中的任意数,那a+1,a+2…a+x也是一定能凑出来的),那如果a>x+1, 区间由[0,x]变为[0,x]并[a,x+a]=[0,x]并[x+2,x+a],缺少x+1,此时x+1就是我们要求的答案,当然要先从小到大排序,以保证维护的正确性
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[110000];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(nullptr);
int i,j,k,n;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int ans=0;//起初为0,是我们能凑出来的范围最大值
for(i=0;i<n;i++)
{
if(a[i]<=ans+1)
ans+=a[i];
else
break;
}
cout<<ans+1<<"\n";
}