金山云10.19笔试
题目1,dfs,AC100%
public class Main {
/*
@金山云1
时间限制: 3000MS
内存限制: 589824KB
题目描述:
现在给你N个正整数,从中选取3个数字的和,刚好能够组成M的倍数。请问存在多少种不同的选取方案?
相同的一组数如果次序不同只能算做一种方案,不同位置的相同数字需当做同一个数字看待。
例如一组数字[2,3,3,4],从中选取3个数字的和来组成3的倍数,只存在一种方案(2,3,4)。
输入描述
单组数据。 第1行输入两个正整数N和M,N<=20。 第2行输入N个正整数,两两之间用空格隔开。
输出描述
输出不同的选取方案的数量。
样例输入
4 3
2 3 3 4
样例输出
1
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
int[] arr = new int[N];
// 读取N个数据...
for (int i = 0; i < N; i++) {
arr[i] = scanner.nextInt();
}
long[] result = new long[1];
Set<String> set = new HashSet<>();
// dfs2(arr, set, new ArrayList<>(), 0);
dfs(arr, set, new ArrayList<>(), new boolean[arr.length]);
set.forEach(e -> {
int sum = Arrays.stream(e.split("_")).mapToInt(Integer::parseInt).sum();
if ((sum) % M == 0) {
result[0]++;
}
});
System.out.println(result[0]);
}
/**
* AC 100% 全排列---
*/
public static void dfs(int[] arr, Set<String> set, List<Integer> list, boolean[] visited) {
if (list.size() == 3) {
if (isValid(set, list)) {
set.add(getString(list, 0, 1, 2));
}
return;
}
for (int i = 0; i < arr.length; i++) {
if (visited[i]) {
continue;
}
visited[i] = true;
list.add(arr[i]);
dfs(arr, set, list, visited);
list.remove(list.size() - 1);
visited[i] = false;
}
}
/**
* 会TLE,AC82%,时间复杂度很高---遍历所有元素,可以选择可以不选择...
*/
public static void dfs2(int[] arr, Set<String> set, List<Integer> list, int index) {
if (list.size() == 3) {
if (isValid(set, list)) {
set.add(getString(list, 0, 1, 2));
}
return;
}
// 判断第i个元素要与不要...
for (int i = index; i < arr.length; i++) {
// 第一种选择是当前元素不要...
dfs2(arr, set, list, i + 1);
// 第二种选择是当前元素要...
list.add(arr[i]);
dfs2(arr, set, list, i + 1);
list.remove(list.size() - 1);
}
}
public static boolean isValid(Set<String> set, List<Integer> list) {
return !set.contains(getString(list, 0, 1, 2)) &&
!set.contains(getString(list, 0, 2, 1)) &&
!set.contains(getString(list, 1, 0, 2)) &&
!set.contains(getString(list, 1, 2, 0)) &&
!set.contains(getString(list, 2, 0, 1)) &&
!set.contains(getString(list, 2, 1, 0));
}
public static String getString(List<Integer> list, int... index) {
return list.get(index[0]) + "_" + list.get(index[1]) + "_" + list.get(index[2]);
}
} 题目2.也不太会做,简单dfs搜索去做的,能AC45%,然后TLE了。
public class Main {
/*
@金山云2
时间限制: 3000MS
内存限制: 589824KB
题目描述:
给出n个正整数,这n个正整数中可能存在一些相同的数。现在从这n个数中选取m个正整数,分别记为X1、X2、......、Xm,
使得这m个数满足如下公式: 1/X1 + 1/X2 + ...... + 1/Xm = 1 请问存在多少种不同的数字组合可以使得上述公式得以成立?
输入描述
单组输入。 第1行输入一个正整数n,表示输入的正整数个数。(n<=100) 第2行输入n个正整数,两两之间用空格隔开。
输出描述
输出满足要求的组合个数。如果一个组合都不存在,则输出“No solution!”。
样例输入
6
1 2 2 3 4 4
样例输出
3
提示
对于输入样例中的6个正整数,存在3种和为1的组合,分别是:1=1/1,1=1/2+1/2,1=1/2+1/4+1/4。
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int[] arr = new int[N];
// 扫描N个数据...
for (int i = 0; i < arr.length; i++) {
arr[i] = scanner.nextInt();
}
long[] result = new long[1];
dfs(arr, new ArrayList<>(), 0, result, new HashSet<>());
System.out.println(result[0] == 0 ? "No solution!" : result[0]);
}
/**
* AC 45%测试用例,然后TLE了
*/
public static void dfs(int[] arr, List<Integer> list, int index, long[] result, Set<List<Integer>> set) {
int check = check(list);
if (check == 0) { // 如果符合,那么需要统计
if (!set.contains(list)) {
result[0]++;
set.add(list);
}
return;
}
if (check > 0) {
return;
}
for (int i = index; i < arr.length; i++) {
dfs(arr, list, i + 1, result, set);
list.add(arr[i]);
dfs(arr, list, i + 1, result, set);
list.remove(list.size() - 1);
}
}
public static int check(List<Integer> list) {
long multi = 1;
// 计算累乘和
for (int i = 0; i < list.size(); i++) {
multi *= list.get(i);
}
// 计算除去当前元素的所有元素的乘积之和...
long sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += multi / list.get(i);
}
return Long.compare(sum, multi);
}
}
#金山云##笔经#
搜狐畅游公司福利 1309人发布