我想知道回答总和问题的最小数字*1*2*3*4...*n = k
(*
表示+
或-
)。例如:
k = 0
:+1+2-3 = 0
,因此,答案最小的是3
。k = 4
:-1+2+3 = 4
,所以答案最小的是3
。 k = 12
:-1+2+3+4+5+6-7 = 12
,因此最小答案为7
。
// 4 = -1 + 2 + 3
// 5 = +1-2-3+4-5
// 6 = +1+2+3
// 7 = -1+2-3+4+5
// 8 = -1+2+3+4
// 9 = -1-2+3+4+5
// 10 = +1+2+3+4
// 11 = +1-2+3+4+5
// 12 = -1+2+3+4+5+6-7
// 13 = -1+2-3+4+5+6
// 14 = -1+2+3+4+5
有没有算法可以做到这一点?
import java.util.Random;
import java.util.Scanner;
public class EX_03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int Case = sc.nextInt();
int arr[] = new int[Case];
int sum[] = new int[Case];
int k = 0;
int count = 0;
for (int i = 0; i < Case; i++) {
arr[i] = sc.nextInt();
}
for (int i = 0; i < Case; i++) {
while (true) {
++k;
if(count==0){
sum[i] += k;
count++;}
else{
sum[i] -= k;
}
if(sum[i] == arr[i]) break;
}
}
// 0 = +1+2-3
// 1 = +1
// 2 = +1-2+3
// 3 = +1+2
// 4 = -1+2+3
// 5 = +1-2-3+4-5
// 6 = +1+2+3
// 7 = -1+2-3+4+5
// 8 = -1+2+3+4
// 9 = -1-2+3+4+5
// 10 = +1+2+3+4
// 11 = +1-2+3+4+5
// 12 = -1+2+3+4+5+6-7
// 13 = -1+2-3+4+5+6
// 14 = -1+2+3+4+5
// 15 = 123456
/*
* Random operatorChoice = new Random(); int operator =
* operatorChoice.nextInt(2);
*
* while (k >= 0) { ++k; for (int i = 0; i < Case; i++) { switch
* (operator) { case 0: sum[i] += k; break; case 1: sum[i] -= k; break;
* default: break; } if(sum[i] == arr[i]) break; else continue; } }
*/
for (int i = 0; i < Case; i++) {
System.out.println(k);
}
}
}
示例输入:
12 -3646397
该输入的预期输出:
7 2701
答案 0 :(得分:2)
使用这个想法(由samgak建议):
更改其中一个数字的符号始终会将总和更改为偶数
那么,你需要多少数字才能获得9的总和?它必须是奇数(*1*2*3
或*1*2*3*4*5
或*1*2*3*4*5*6*7
或......) - 这是您需要注意的第一件事。
然后,考虑最大总和:
+1+2+3+...+n
很容易计算这笔钱(我忘了答案,但这很容易)。
然后(这是最重要的一步),尝试改变标志并检查总和会发生什么:
+1+2+3+4+5 = 10
-1+2+3+4+5 = ? (the sum is smaller by an even number)
+1-2+3+4+5 = ? (the sum is smaller by another even number)
+1+2-3+4+5 = ? (the sum is smaller by another even number)
+1+2+3-4+5 = ? (the sum is smaller by another even number)
+1+2+3+4-5 = ? (the sum is smaller by another even number)
从这里开始,制作算法很容易。请记住,您真的不需要打印表达式(总和)本身,只能证明它存在。因此,无需在上面的列表中找到目标号码的确切位置,只需查找该列表的长度即可。
答案 1 :(得分:0)
您可以尝试改进使用递归的代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
*
* @author Aroniaina
*/
public class RandomOperator {
public static HashMap<Integer, List<Integer>> possibilities(Integer current) {
//Return -1 and 1 if current si equal to 1
if (current == 1) {
HashMap<Integer, List<Integer>> result = new HashMap<>();
//Add positive possibility
List<Integer> list1 = new ArrayList<>();
list1.add(current);
result.put(current, list1);
//Add negative possibility
List<Integer> list2 = new ArrayList<>();
list2.add(-1 * current);
result.put(-1 * current, list2);
return result;
} else {
HashMap<Integer, List<Integer>> previous = possibilities(current - 1);
HashMap<Integer, List<Integer>> temp = new HashMap<>();
temp.putAll(previous);
for (Integer prev : previous.keySet()) {
if (previous.get(prev).size() == (current - 1)) {
//Add positive possibility
List<Integer> list1 = new ArrayList<>();
list1.addAll(previous.get(prev));
list1.add(current);
temp.put(current + prev, list1);
//Add negative possibility
List<Integer> list2 = new ArrayList<>();
list2.addAll(previous.get(prev));
list2.add(-1 * current);
temp.put(-1 * current + prev, list2);
}
}
return temp;
}
}
public static void main(String args[]) {
for (int i = 0; i < 20; i++) {
Integer toVerify = i;
int current = 1;
while (true) {
HashMap<Integer, List<Integer>> result = possibilities(current);
if (result.keySet().contains(toVerify)) {
System.out.print(toVerify + " = ");
for (Integer e : result.get(toVerify)) {
System.out.print(e > 0 ? ("+" + e) : (e));
}
break;
}
current++;
}
System.out.println("");
}
}
}
输出:
0 = -1-2+3
1 = +1
2 = +1-2+3
3 = +1+2
4 = -1+2+3
5 = +1+2+3+4-5
6 = +1+2+3
7 = -1+2-3+4+5
8 = -1+2+3+4
9 = -1-2+3+4+5
10 = +1+2+3+4
11 = +1-2+3+4+5
12 = -1+2+3+4+5+6-7
13 = -1+2+3+4+5
14 = +1+2+3+4+5+6-7
15 = +1+2+3+4+5
16 = +1+2+3+4+5-6+7
17 = +1-2+3+4+5+6
18 = +1+2+3+4-5+6+7
19 = -1+2+3+4+5+6