牛客周赛18-题解
A. 游游的整数翻转
思路: 按照题目进行模拟即可,可以使用 StringBuilder工具类快速处理进行翻转;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String x = input.nextInt() + "";
int k = input.nextInt();
StringBuilder ans = new StringBuilder();
ans.append(x.substring(0, k)).reverse();
while (ans.charAt(0) == '0') {
ans = new StringBuilder(ans.substring(1));
}
ans.append(x.substring(k));
System.out.println(ans.toString());
}
}
B. 游游的排列统计
思路:
- 首先 n 的范围是 2 - 10,相邻元素和最大是 19,所以素数分别是:2, 3, 5, 7, 11, 13, 17, 19;
- 全排列标准代码,用 ans 记录一下次数;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
Set<Integer> prime = new HashSet<>();
prime.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19));
ans = 0;
dfs(new ArrayList<>(), new boolean[n + 1], prime, n);
System.out.println(ans);
}
static int ans = 0;
private static void dfs(List<Integer> curr, boolean[] vis, Set<Integer> prime, int n) {
if (curr.size() == n) {
ans++;
return;
}
for (int i = 1; i <= n; i++) {
if (vis[i]) {
continue;
}
if (curr.size() == 0 || !prime.contains(curr.get(curr.size() - 1) + i)) {
curr.add(i);
vis[i] = true;
dfs(curr, vis, prime, n);
vis[i] = false;
curr.remove(curr.size() - 1);
}
}
}
}
C. 游游刷题
思路:
- 所有数据对 k 进行取模处理,数据范围 0 - k,使用 map 进行计数,由于 k 的数据范围是 1 ~ 1e9,使用数组记录会报错超内存;
- 对于模数为 0 的数据可以单独算作一天;
- 其他的数直接进行配对,i + j = k 即可,当 k 为偶数时需要特殊处理,直接使用 k/2 即可满足,将个数除以 2 即可;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int k = input.nextInt();
Map<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < n; i++) {
int t = input.nextInt() % k;
map.put(t, map.getOrDefault(t, 0) + 1);
}
int ans = map.containsKey(0) ? map.get(0) : 0;
for (Map.Entry<Integer, Integer> e : map.entrySet()) {
int key = e.getKey();
int val = e.getValue();
if (key * 2 >= k) {
break;
}
ans += Math.min(val, map.containsKey(k - key) ? map.get(k - key) : 0);
}
if (k % 2 == 0) {
ans += (map.containsKey(k / 2) ? map.get(k / 2) : 0) / 2;
}
System.out.println(ans);
}
}
D. 游游买商品
思路:
- 使用 01 背包的思路进行考虑,dp[i][j] 表示前 i 个商品,总价格不超过 j 时,最大的喜爱度总和,可得到一下转移方程:
dp[i][j] = dp[i-1][j]
dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i]]+ b[i]), j>=a[i]
dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i-1]-a[i]/2]+b[i-1]+b[i]/2), j>=a[i-1]+a[i]/2
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int x = input.nextInt();
int[] a = new int[n + 1];
int[] b = new int[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = input.nextInt();
}
for (int i = 1; i <= n; i++) {
b[i] = input.nextInt();
}
long[][] dp = new long[n + 1][x + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= x; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= a[i]) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - a[i]] + b[i]);
}
if (i >= 2 && j >= a[i - 1] + a[i] / 2) {
dp[i][j] = Math.max(dp[i][j], dp[i - 2][j - a[i - 1] - a[i] / 2] + b[i - 1] + b[i]);
}
}
}
System.out.println(dp[n][x]);
}
}