1.素数的个数
给出一个包含n个正整数的数组a,把a[i]拆分为若干个和为a[i]的素数,求拆分后最多能有多少个素数。
第一行数据为n,表示数组长度,第二行为n个元素。
输入
3
1 1 1
输出
0 1不可拆分
输入
1 3 5 7
6 1为0个,3为1个,5为(2,3),7为(2,2,3)
思路:每个数除2即是答案,注意答案用long类型,int只能通过30%
package 网易0808;
import java.util.Scanner;
public class Num1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
long sum = 0;
for (int i = 0; i < n; i++) {
int t = scanner.nextInt();
sum += t / 2;
}
System.out.println(sum);
}
}
2.字典序最小的排列
给出一个长度为m的序列T,求一个长度为n且字典序最小的排列S,要求不改变原序列中元素的相对位置。
第一行输入两个正整数n和m
第二行输入m个数,表示序列
5 3
2 1 5 ....T
输出
2 1 3 4 5 ....S
思路:需要找到数的个数为n-m个,首先需要枚举S中需要的元素,即S中比T中多出来的n-m个元素。如果n是5那么就需要从1开始找1.2.3... 在T中没有出现过的元素。这样就可以把T中的元素存进一个Set中,找的过程中只要在set中出现过的元素就跳过,没出现过就添加到需要的元素数组中。然后将两个数组归并排序即是答案所需要的数组。
package 网易0808;
import java.util.HashSet;
import java.util.Scanner;
public class Num2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[] arr = new int[m];
HashSet<Integer> set = new HashSet<>();
for (int i = 0; i < m; i++) {
arr[i] = scanner.nextInt();
set.add(arr[i]);
}
int[] need = new int[n - m];
int index = 1;
for (int i = 0; i < need.length; i++) {
while (set.contains(index)) index++;
need[i] = index++;
}
int i = 0, j = 0;
index = 0;
int[] ans = new int[n];
while (i < arr.length && j < need.length) {
if (arr[i] < need[j]) ans[index++] = arr[i++];
else ans[index++] = need[j++];
}
while (i < arr.length) ans[index++] = arr[i++];
while (j < need.length) ans[index++] = need[j++];
for (int an : ans) System.out.print(an + " ");
}
}
3.丢弃最少物品
给出n个物品,每个物品都有自己的价值,每个物品只有一件,这些物品需要分给两个人,要求分配完之后,两个人的物品价值相同。分配完成之后,会丢弃剩下的物品,求最少要丢弃多少物品。
输入
输入第一行为总的测试数据个数,第二行为物品个数n,第三行为n个物品的价值。
1
5
30 60 5 15 30
输出
20 丢弃5和15,把60分配给第一个人,2个30分配给第二个人。
(n<15)重点
思路: 刚开始做的时候想着用背包问题来解决,但是无法确定背包容量,也无法确定要丢弃的物品,没思路放弃了。这题有个很关键的条件就是n<=15,意味着用暴搜三种状态选择,1.物品分给A,2.物品分给B,3.物品分给C,那么dfs的复杂度最大为 3^15=14348907=1.4*10^8。一般只要复杂度不超过10^9都是可以AC的。所以这题直接用dfs暴搜索,做题也要注意看数量大小范围。可以看出做题的方法。
package 网易0808;
import java.util.Scanner;
public class Num3 {
static int ans;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
for (int i = 0; i < t; i++) {
ans = Integer.MAX_VALUE;
int n = scanner.nextInt();
int[] arr = new int[n];
for (int j = 0; j < n; j++)
arr[j] = scanner.nextInt();
dfs(arr, 0, 0, 0, 0);
System.out.println(ans);
}
}
private static void dfs(int[] arr, int index, int sumA, int sumB, int sumDrop) {
if (index == arr.length) {
if (sumA == sumB) {
ans = Math.min(sumDrop, ans);
}
return;
}
dfs(arr, index + 1, sumA + arr[index], sumB, sumDrop);
dfs(arr, index + 1, sumA, sumB + arr[index], sumDrop);
dfs(arr, index + 1, sumA, sumB, sumDrop + arr[index]);
}
}
4.差距最小的生成树
给出一个无向图,一共有n个点,m条边,每条边的权值为v。 求一个生成树,使得图保持联通的同时,权值的最大值和最小值之差最小。
输入
第一行为n和m,表示点的个数和边的条数
后面为m行,表示m条边的两个顶点和其权值
3 5
1 2 10
1 3 5
3 1 12
2 3 19
1 2 74
输出
2 选择边1和3,最小差值为12-10