小易的幸运数字是7,现有一个整数数组 nums,请你找出并返回能被七整除的子集合的最大和,如果找不到则返回-1。
一个正整数数组列表nums,用空格区分,1<=length(nums)<=100000,sum(nums) <= 1000000000
一个整数,最大和
7 3 1 4
14
7+3+4
6 5
-1
找不到 一个子数组,和能被7整除
10 20 2 29
49
20+29
这道题很难, 一开始会想到遍历得到所有的子集合的和, 但是却不知道如何遍历得到。因为这里的子集合长度可以为1 ~ nums.length,一般的遍历无法满足!
举例: 1 2 3 4
一般的遍历是 1, 1 2, 1 2 3, 1 2 3 4, 2, 2 3, 2 3 4, 3,3 4,4实现这个遍历已经是O(n^2)的复杂度了! 可是这还没结束, 还需要 1 3, 1 3 4, 1 4, 2 4, 这种循环遍历极其难写出来!!
🌟那我们这里想到了一个巧妙地方法, 逆向思维, 由于全部的数之和sum肯定是由所有的数组成, 那我们可以试着慢慢地扒元素下来直到把所有元素扒完,
const readline=require('readline'); const rl=readline.createInterface({ input:process.stdin, output:process.stdout }); /* 小易的幸运数字是7,现有一个整数数组 nums, 请你找出并返回能被七整除的子集合的最大和,如果找不到则返回-1 输入: 一个正整数数组列表nums,用空格区分,1<=length(nums)<=100000,sum(nums) <= 1000000000 */ rl.on('line',function (line) { /*1.处理数据*/ let arr=line.trim().split(' ').map(Number); /*2.dp*/ //由于是全是正整数,所以 sum >= arr.length let sum=arr.reduce((a,b)=>a+b); //dp[i]记录i是否能够得到 1为可得到,0则相反 let dp=new Array(sum+1).fill(0); dp[0]=1; dp[sum]=1; /*这个方法很巧妙, 最初是a+b+c+d,每次从所有的满足条件的子集合减去一个数 * 这样就很方便的得到了所有的排列*/ for (let i=0;i<arr.length;i++){ for (let j=0;j<=sum;j++){ if (dp[j]===1&&j>=arr[i]){ dp[j-arr[i]]=1; } } } let maxSum=-1; for (let i=dp.length-1;i>=7;i--){ if (dp[i]===1&& i%7===0){ maxSum=i; break; } } console.log(maxSum); })
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] strArr = br.readLine().split(" "); int[] arr = new int[strArr.length]; int sum = 0; for(int i = 0; i < strArr.length; i++) { arr[i] = Integer.parseInt(strArr[i]); sum += arr[i]; } // 求解背包问题 int[] dp = new int[sum + 1]; // dp[i]用来记录i是否能得到 dp[0] = 1; dp[sum] = 1; for(int i = 0; i < arr.length; i++){ dp[i] = 1; for(int j = 0; j <= sum; j++) if(dp[j] == 1 && j >= arr[i]) dp[j - arr[i]] = 1; } // 降序遍历能取到的总和,输出最大的 for(int lucky = sum; lucky >= 0; lucky--){ if(dp[lucky] == 1 && lucky % 7 == 0){ System.out.println(lucky); break; } } } }
lyst = list(map(int, input().split())) # 数组所有数字之和 total = 0 for i in lyst: total += i # 数组排序 lyst.sort() res = [total] flag = False for i in lyst: # 注意此处不能直接用res循环,否则后面append之后res长度增加还会继续循环内层 res_set = set(res) for j in res_set: temp = j - i if temp % 7 == 0: flag = True print(temp) break else: res.append(temp) if flag: break if not flag: print(-1)
import sys from math import inf l = [int(s) for s in input().split()] l.sort() n = len(l) prev = [0] * 7 prev[l[0] % 7] = l[0] for i in range(1, n): dp = prev.copy() cur = l[i] % 7 dp[cur] = max(prev[cur], l[i]) for j in range(7): if prev[j] != 0: idx = (j + l[i]) % 7 dp[idx] = max(prev[idx], prev[j] + l[i]) prev = dp print(prev[0])
#include<iostream> #include<vector> using namespace::std; int main() { vector<int> nums; int x; long sum; do{ cin>>x; nums.push_back(x); sum+=x; }while(cin.get()!='\n'); vector<vector<int>> dp(nums.size()+1,vector<int>(7,sum)); dp[0][sum%7]=0; for(int i=1;i<nums.size()+1;i++) { int x=nums[i-1]; for(int j=0;j<7;j++) { dp[i][j]=min(dp[i-1][j],dp[i-1][(x%7+j)%7]+x); } } cout<<sum-dp.back()[0]<<endl; }
//暴力搜索 #include <bits/stdc++.h> using namespace std; int ret = 0; void backTracking(const vector<int>& nums,int sum, int index) { if(index >= nums.size()) { if(sum % 7 == 0) ret = max(ret, sum); return; } for(int i = index;i < nums.size();i++) { sum += nums[i]; backTracking(nums, sum, i+1); sum -= nums[i]; } } int main() { vector<int> nums; int num; while(cin >> num) nums.push_back(num); backTracking(nums, 0, 0); cout << ret << endl; return 0; }
#include <bits/stdc++.h> using namespace std; int main() { int n; vector<int> nums; int max_sum = -1; int sum = 0; while(scanf("%d", &n) != EOF) { sum += n; int rest = n % 7; // 加入所有7的整数倍 if(rest != 0) { nums.push_back(n); } } int rest = sum % 7; // 刚好是7的倍数 if(rest == 0) { cout << sum << endl; return 0; } //每组都排序 sort(nums.begin(), nums.end()); int tmp_sum = 0; function <void(int)> dfs = [&](int deps) { if(deps == -1) { return ; } // 不加入直接判断 if(tmp_sum % 7 == rest && tmp_sum != sum) { max_sum = sum - tmp_sum; return ; } dfs(deps - 1); // 加入 tmp_sum += nums[deps]; if(tmp_sum % 7 == rest && tmp_sum != sum) { max_sum = sum - tmp_sum; return ; } dfs(deps - 1); //还原 tmp_sum -= nums[deps]; return ; }; for(int i = 0; i < nums.size(); i++) { tmp_sum = 0; dfs(i); if(max_sum != -1) { break; } } cout << max_sum << endl; return 0; }
import java.io.*; import java.util.*; public class Main{ public static void main(String[] args) throws IOException{ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String[] ss = reader.readLine().split(" "); Set<Integer> set=new HashSet(); set.add(0); Integer ans=Integer.MIN_VALUE; for(String s:ss ){ Iterator<Integer> it=set.iterator(); Set<Integer> set2=new HashSet(); while(it.hasNext()){ Integer t=it.next(); Integer v=Integer.parseInt(s)+t; set2.add(t); set2.add(v); if(v%7==0 && v>ans){ ans=v; } } set=set2; } if(ans==Integer.MIN_VALUE){ System.out.println(-1); } else{ System.out.println(ans); } } }
import java.io.*; public class Main{ public static void main(String[] args) throws IOException{ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String[] s = reader.readLine().split(" "); int sum = 0; int[] arr = new int[s.length]; for(int i = 0 ; i < s.length ;i++){ arr[i] = Integer.parseInt(s[i]); sum += arr[i]; } int[] dp = new int[sum+1]; dp[sum] = 1; dp[0] = 1; for(int i = 0 ; i < arr.length;i++){ for(int j = 0; j <= sum;j++) if(dp[j] == 1 && j >= arr[i]) dp[j - arr[i]] = 1; } for(int lucky = sum; lucky >= 0; lucky--){ if(dp[lucky] == 1 && lucky % 7 == 0){ System.out.println(lucky); break; } } } }