1、志愿填报4719
( gaokao)
【问题描述】
众所周知,今天是高考的第二天,正所谓“月儿弯弯照九州,几家欢喜几家愁”。而高考志愿填报更是抉择的时候,其中每年的高考的志愿填报都是使用的 1、2、4、8 来表示数字,如要填涂 7 则选择 1、2、4 三个数字, Pray2018 作为 1‰的数学爱好者,他决定研究这一问题, 即, 给出 n 个互不相同的正整数, 记为 s[i] , 每个正整数只能使用一次,求这 n 个数 不能组合得到的最小值。
【输入说明】
第一行是一个正整数 n,表示正整数的个数。
接下来的 n 行每行一个正整数。
【输出说明】
一个正整数,表示这 n 个数 不能组合得到的最小值。
【样例输入】
4 1 2 4 8
【样例输出】
16
【数据规模 与约定】
对于 30%的数据,n<=500,s[i]<=1000;
对于 70%的数据,n<=1000,s[i]<=10000;
对于 100%的数据,n<=100000,s[i]<=100000。
1.此题解法可用01背包,只要你不爆炸(滑稽)
2、我们假设前i个数中1->sum的值已经可以全部达到,那么如果S[i+1]>sum+1,则sum+1无法取得。否则可以表示出1->sum+S[i+1]的值。所以可以对序列S排序,然后水过。
3、歪门邪道:我们可以想到,这道题的数据并不好生成,尤其在数据较大的时候,无法达到的值很容易就变成了S[i]累加起来加1,而这种方法可以水过60分。
这题实际上就与去年的小凯的疑惑很像,但是完全不同,这题纯粹靠乱搞(哈哈哈哈哈哈哈哈)
不过正经的来说,我们其实首先应该有最优化排序的意识,01背包的实质在于更新,但这道题的特点是找出最小,所以我们并不关心那些很大的值,我们只关心能不能凑出小的值,尤其是这个1->sum思想
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int a[1000005]; 6 int main(){ 7 int n; 8 cin>>n; 9 for(int i=1;i<=n;i++)cin>>a[i]; 10 sort(a+1,a+n+1); 11 int sum=0; 12 for(int i=1;i<=n;i++){ 13 if(sum+1<a[i])break; 14 sum+=a[i]; 15 } 16 cout<<sum+1; 17 return 0; 18 }
over