目录
- A - Three Threes
- B - Pentagon
- C - Repunit Trio
- D - Erase Leaves
- E - Takahashi Quest
A - Three Threes
原题链接
题目描述
讲一个数字n
输出n
次。
public static void solve() throws IOException {int n = readInt();printWriter.println(String.valueOf(n).repeat(n));
}
B - Pentagon
原题链接
题目描述
一个有五个顶点的等边菱形,现在给出菱形两条边,判断这两条边的长度是否相等。
思路:数据结果
- 使用两个
set
存在长度相等的所有边。
public static void solve() throws IOException {Set<String> set1 = new HashSet<>(), set2 = new HashSet<>();set1.add("AB");set1.add("BA");set1.add("BC");set1.add("CB");set1.add("CD");set1.add("DC");set1.add("ED");set1.add("DE");set1.add("AE");set1.add("EA");set2.add("AD");set2.add("AC");set2.add("BE");set2.add("BD");set2.add("CA");set2.add("CE");set2.add("DA");set2.add("DB");set2.add("EB");set2.add("EC");String s = readString(), s2 = readString();printWriter.println((set1.contains(s) && set1.contains(s2)) || (set2.contains(s) && set2.contains(s2)) ? "Yes" : "No");
}
C - Repunit Trio
原题链接
题目描述
一种repunit
数它的十进制数位都是1
。按升序排列的repunits
是1
,11
,111
,…。求出可以表示为恰好三个repunits
之和的第n
小的整数。
思路:全排列
- 深搜枚举出所有可以由三个
repunit
数可以表示出的和。
static long[] arr =
new long[]{1, 11, 111, 1111, 11111, 111111, 1111111, 11111111, 111111111, 1111111111, 11111111111l, 111111111111l};
static List<Long> list = new ArrayList<>();public static void solve() throws IOException{int n = readInt();dfs(0, 0);Collections.sort(list);printWriter.println(list.get(n - 1));
}static long sum = 0;
public static void dfs(int u, int cnt) {if (cnt == 3) {list.add(sum);return;}for (int i = u; i < arr.length; i++) {sum += arr[i];dfs(i, cnt + 1);sum -= arr[i];}
}
D - Erase Leaves
原题链接
题目描述
给你一棵有 N N N 个顶点的树:顶点 1 , 1, 1, 顶点 2 2 2, … \ldots …, 顶点 N N N。 i i i-th 边 ( 1 ≤ i < N ) (1\leq i\lt N) (1≤i<N) 连接顶点 u i u _ i ui 和顶点 v i v _ i vi。考虑重复下面的操作若干次:
- 选择一个叶顶点 v v v,删除它和所有的附带边。
求删除顶点 1 1 1 所需的最少操作次数。
思路:深搜
- 枚举节点
1
的每个邻点,假设有k
个邻点,深搜求出删除k
个邻点的所需操作数,按照操作数升序排序后,答案为删除前k-1
个邻点的操作数之和+1,因为节点1
也要被删除。
static List<Integer>[] edges;
static int res = 1 << 30;
public static void solve() throws IOException{int n = readInt();edges = new List[n + 10];Arrays.setAll(edges, e -> new ArrayList<>());for (int i = 0; i < n - 1; i++) {int a = readInt(), b = readInt();edges[a].add(b);edges[b].add(a);}if (edges[1].size() == 1) {printWriter.println(1);return;}List<Integer> list = new ArrayList<>();// 遍历节点1的所有邻点for (int i = 0; i < edges[1].size(); i++) {list.add(dfs(edges[1].get(i), 1));}Collections.sort(list);int sum = 0;for (int i = 0; i < list.size() - 1; i++) sum += list.get(i);printWriter.println(sum + 1);
}public static int dfs(int u, int pa) {if (edges[u].size() == 1) return 1;int sum = 1;for (int i = 0; i < edges[u].size(); i++) {int p = edges[u].get(i);if (p != pa) {// 不再向上搜sum += dfs(edges[u].get(i), u);}}return sum;
}
E - Takahashi Quest
原题链接
题目描述
有 N N N 个事件。第 i i i个事件 ( 1 ≤ i ≤ N ) (1\leq i\leq N) (1≤i≤N) 由一对整数 ( t i , x i ) (t _ i,x _ i) (ti,xi) 表示。
- 如果 t i = 1 t _ i=1 ti=1,你找到了一个 x i x _ i xi类型的药水。你可以选择捡起或丢弃。
- 如果 t i = 2 t _ i=2 ti=2,你将遇到一只 x i x _ i xi 类型的怪物。如果你有 x i x _ i xi型药水,你可以使用一种药水击败怪物。如果你没有打败怪物,那么你就会被打败。
判断你是否可以打败所有怪物。如果你无法打败所有怪物,则输出
-1
。否则,让 K K K成为在你不被打败的前提下手中最小需要拥有的药水数量,打印 K K K的值以及实现 K K K的行动。
思路:逆向思维+枚举
- 从后往前遍历每个事件,使用数组
cnt
记录下每种类型的药水需要的数量,tc
表示还有多少怪兽没有解决,max
表示最多还有多少怪兽没有解决,也就是上面的K
。
public static void solve() throws IOException{int n = readInt();int[] t = new int[n + 5], x = new int[n + 5];for (int i = 0; i < n; i++) {t[i] = readInt();x[i] = readInt();}int[] cnt = new int[n + 5];boolean[] st = new boolean[n + 5];int tc = 0, max = 0;for (int i = n - 1; i >= 0; i--) {if (t[i] == 1) {if (cnt[x[i]] > 0) {// 拥有这种类型的药水,可以抵消cnt[x[i]]--;tc--;st[i] = true;// 该位置使用了药水}} else {cnt[x[i]]++;tc++;}max = Math.max(max, tc);}if (tc > 0) {// 怪兽没打完printWriter.println(-1);return;}printWriter.println(max);for (int i = 0; i < n; i++) {if (t[i] == 1) {printWriter.print((st[i] ? 1 : 0) + " ");}}
}