输入第一行为数字个数n (n ≤ 20) 第二行为n个数xi (1 ≤ xi ≤ 100000)
输出最小不能由n个数选取求和组成的数
3 5 1 2
4
import java.util.*; /** * 背包问题的一种,本质为"若num小于不可解的最小数,那么1,2,3...num都是可解的"。 * * 思路如下: * * 将给定的数据集nums从大到小排序。我们要判断命题"num小于不可解的最小数"是否成立。 * 我们将num看作背包,然后从nums中拿出一个最大的值v,如果num中能够放得下就放进去, * 如果放进去后刚好满了,则num可解,命题成立,如果不满继续迭代;如果v放不进去背包中了, * 那么背包剩下的容量构成一个更小的子问题(<num),并且如果想要命题成立,那么该子问题 * 必定可解,并且解必定由v后边的数字序列构成(已从大到小排序)。 */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int[] nums = new int[n]; for(int i=0; i<n; i++) nums[i] = scanner.nextInt(); Arrays.sort(nums); long num = 1; while (true) { long sum = 0; for(int i=n-1; i>=0 && sum!=num; i--) { if(nums[i] + sum <= num) sum += nums[i]; } if (sum != num) { System.out.println(num); break; } num++; } } } }
//将数组vec所有元素排序,比如:1,2,5,6... //前i-1个元素的和sum,初始值设为0,每次判断sum+1与第i个元素的大小关系 //(sum+1与vec[i]),若sum+1<vec[i],说明sum与vec[i]之间出现了断裂,sum+1 //即为最小的断裂元素(不可能由前面的元素组合成)。 //比如当i=2时,sum=vec[0]+vec[1]=1+2=3,则0~3是可以连续取到的,而此时sum+1<5, //即3~5之间出现了断裂,4是取不到的。 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { int n; while(cin>>n) { vector<int> vec; for(int i=0;i<n;i++) { int number; cin>>number; vec.push_back(number); } sort(vec.begin(),vec.end()); long long sum=0; int i; for(i=0;i<n;i++) { if(sum+1<vec[i]) break; sum+=vec[i]; } cout<<sum+1<<endl; } }
#include<stdio.h> #include<string.h> int a[25],book[2000005]; int main(){ int N,i,j; //freopen("input.txt","r",stdin); while(scanf("%d",&N)!=EOF){ memset(book,0,sizeof(book)); for(i=0;i<N;i++) scanf("%d",&a[i]); for(i=0;i<1<<N;i++){ int res=0; for(j=0;j<N;j++) if(i>>j&1) res+=a[j]; book[res]=1; } for(i=1;i<=2000000;i++) if(book[i]==0) break; printf("%d\n",i); } }//这么小的数据,直接枚举所有子集就可以啦~
import java.util.*; public class Main{ public static int minNum(int[] num){ Arrays.sort(num); int number=1; if(num[0]!=1){ return 1; } if(num.length==1){ return num[0]+1; } else{ for(int i=1;i<num.length;i++){ if(num[i]-number>1){ break; } else{ number+=num[i]; } } } return number+1; } public static void main(String[] args){ Scanner s=new Scanner(System.in); while(s.hasNext()){ int n=s.nextInt(); int num[]=new int[n]; for(int i=0;i<n;i++){ num[i]=s.nextInt(); } System.out.println(minNum(num)); } } }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine().trim()); String[] strArr = br.readLine().split(" "); int[] arr = new int[n]; for(int i = 0; i < n; i++) arr[i] = Integer.parseInt(strArr[i]); System.out.println(solve(arr)); } private static int solve(int[] arr) { Arrays.sort(arr); if(arr[0] > 1) return 1; if(arr.length == 1) return arr[0] + 1; int sum = arr[0]; for(int i = 1; i < arr.length; i++){ if(arr[i] > 1 + sum) break; else sum += arr[i]; } return sum + 1; } }
先排序
a1 a2 .... an 升序
首先若a1!=1,那么最小不能组合的数为1
否则
sum(1)=a1表示前1个数之和,且sum(1)之内的数都可组合得到
设sum(i)为前i个数之和,且sum(i)之内的数都可以组合得到
则对于sum(i+1)而言
若a(i+1)-sum(i)>1,则表示前i个数之和小于a(i+1),也就是说前i个数无法组合成a(i+1)-1,
也就是说sum(i)和a(i+1)之间必有不能组合的整数,且最小为sum(i)+1;则找到不能组合的最小的数
若a(i+1)-sum(i)<=1,则sum(i+1)之内的任何数字都可以组合得到因为sum(i)之内的任何数可以得到且ai+1可以得到
如此递推下去
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n=Integer.parseInt(br.readLine());
int x[]=new int[n];
String[] strs=br.readLine().split(" ");
for(int i=0;i<n;i++){
x[i]=Integer.parseInt(strs[i]);
}
//排序
Arrays.sort(x);
if(x[0]>1){
System.out.println(1);
return;
}
int sum=0;
for(int i=0;i<n-1;i++){
sum+=x[i];
if(x[i+1]-sum>1){
System.out.println(sum+1);
return;
}
}
System.out.println(sum+x[n-1]+1);
}
while True: try: num,digitList = int(input()),list(map(int,input().split())) digitList.sort() pieceNum = 0 #表示此前已经可以拼凑前pieceNum的数了 for i in digitList: if pieceNum+1 >= i: #如果当前i比pieceNum+1还要大,则这些数凑不出pieceNum+1 pieceNum += i #此时能凑的最大数为pieceNum+i else: print(pieceNum+1) break else: print(pieceNum+1) except Exception: break
import java.util.*; //先排序,记录可以累加到的和在map中,按顺序遍历,一旦出现空缺元素那就是不能累加到的第一个元素 public class Main{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String line = scanner.nextLine(); int n = Integer.parseInt(line); line = scanner.nextLine(); String []s = line.split(" "); int []arr = new int[n]; for (int i = 0;i < n;i ++) { arr[i] = Integer.parseInt(s[i]); } System.out.println(min(arr)); } public static int min(int []arr) { Arrays.sort(arr); if (arr[0] != 1) { return 1; } int max = arr[0]; LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>(); Set<Integer> set = map.keySet(); for (int i = 0;i < arr.length;i ++) { if (arr[i] - max > 1)return max + 1; List<Integer> list = new ArrayList<>(); for (int j : set) { list.add(j + arr[i]); max = Math.max(max, j + arr[i]); } for (int num : list) { map.put(num, 1); } map.put(arr[i], 1); } return max + 1; } }
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int n; cin>>n; vector<int> data; int tmp; for(int i=0; i<n; i++){cin>>tmp; data.push_back(tmp);} sort(data.begin(), data.end()); if(data[0]!=1){cout<<1<<endl; return 0;} int res = 1; for(int i=1; i<data.size(); i++){ if(data[i]<=res+1) res+=data[i]; if(data[i]>res+1) break; } cout<<res+1<<endl; return 0; }
#include <iostream> #include <vector> #include <map> #include <numeric> #include <limits> using namespace std; /*参考了 牛客470556号 的思想 有数列a1~an升序排列 设a1~ai 可以组成数字 1~m 则a(i+1)-1<=m 因为a1~a(i+1)即a1~ai~a(i+1),显然可以组成{a(i+1)、a(i+1)+1、a(i+1)+2、...、a(i+1)+m}中任意一个数,最小的就是a(i+1) 所以a(i+1)不能大于(m+1),否则就会出现空档,即无法组成的数字 */ int main() { int n; cin >> n; map<int, int> m; for(int i=0;i<n;i++) { int tmp; cin >> tmp; m[tmp] += 1; } map<int, int>::iterator it = m.begin(); int max; if (it->first > 1) max = 0; else { max = (it->first)*(it->second); for (it++; it != m.end(); it++) { if (max >= ((it->first) - 1)) max += (it->first)*(it->second); else break; } } cout << ++max; return 0; }
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int i,j,n,temp; vector<int> v; cin>>n; for(i=0;i<n;i++){ cin>>temp; v.push_back(temp); } sort(v.begin(),v.end()); long long int sum=0; for(j=0;j<v.size();j++){ if(v[j]>sum+1){ break; }else{ sum+=v[j]; } } cout<<sum+1<<endl; return 0; }
//最笨的方法,把所有的和计算出来,然后不能求和的 // 注意:相同的数字的处理 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc= new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); int[] num = new int[n]; int sum = 0; for(int i=0;i<n;i++){ num[i] = sc.nextInt(); sum += num[i]; } boolean[] s = new boolean[sum+1]; boolean flag = false; for(int i=0;i<n;i++){ if(s[num[i]]){ flag = true; }else{ s[num[i]] = true; } for(int j=sum;j>=0;j--){ if(flag){ if(s[j])s[j+num[i]]=true; }else{ if(j!=num[i] && s[j])s[j+num[i]]=true; } } flag = false; } flag = false; int min = 1; for(;min<=sum;min++){ if(!s[min]){ break; } } if(min==sum+1){ System.out.println(sum+1); }else{ System.out.println(min); } } } }
import java.util.Scanner; import java.util.Arrays; public class Main { public static void main(String[] args) { //输入 Scanner sc = new Scanner(System.in); int count = sc.nextInt(); int[] nums = new int[count]; for (int i = 0; i < count; i++) { nums[i] = sc.nextInt(); } //排序 Arrays.sort(nums); //特例,没有1直接输出1 if (nums[0] > 1) { System.out.println(1); return; } //依次求和 int sum = 0; for (int i = 0; i < count - 1; i++) { sum += nums[i]; if (sum + 1 < nums[i + 1]){ System.out.println(sum + 1); return; } } System.out.println(sum + nums[count - 1] + 1); } }
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
using namespace std;
typedef long long ll;
int a[1005];
int main(){
int miss=0;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
sort(a,a+n);
for(int i=0;i<n;i++){
if(a[i]>miss+1) break;
miss+=a[i];
}
printf("%d\n",miss+1);
return 0;
}