文章目录
- [A - Exponential Plant](https://atcoder.jp/contests/abc354/tasks/abc354_a)
- [B - AtCoder Janken 2](https://atcoder.jp/contests/abc354/tasks/abc354_b)
- [C - AtCoder Magics](https://atcoder.jp/contests/abc354/tasks/abc354_c)
- [D - AtCoder Wallpaper](https://atcoder.jp/contests/abc354/tasks/abc354_d)
- [E - Remove Pairs](https://atcoder.jp/contests/abc354/tasks/abc354_e)
- 模板代码
A - Exponential Plant
题目:
一颗植物初始高度为0厘米,第i天晚上增加 2i 厘米,问第几天早上植物高度严格大于H?
思路:
遍历直到找到符合条件的i
static void solve() throws IOException {
long a = pLong();
int i = 0;
long h = 0;
while (true) {
if (h > a) {
out.println(i);
return;
}
h += (1L << i);
i++;
}
}
B - AtCoder Janken 2
题目:
N个玩家玩游戏,第i个玩家的名字为 Si以及分数为 Ci,将玩家的名字按字典序排序并从0~N-1编号,然后将玩家分数总和对N取模,编号和取模结果相同的玩家胜利,问胜利的玩家名字;
思路:
模拟
static class Pair {
String name;
int score;
public Pair(String n, int s) {
name = n;
score = s;
}
}
static void solve() throws IOException {
int n = pInt();
Pair[] pairs = new Pair[n];
long sum = 0;
for (int i = 0; i < n; i ++) {
String[] ins = pStringArray();
pairs[i] = new Pair(ins[0], pInt(ins[1]));
sum += pairs[i].score;
}
Arrays.sort(pairs, Comparator.comparing(a -> a.name));
long m = sum % n;
out.println(pairs[(int) m].name);
}
C - AtCoder Magics
题目:
有N张卡牌,每张卡牌有对应的强度Ai 和费用Ci,对于任意满足 Ax > Ay 且 Cx < Cy 的两张牌x和y,丢弃牌y;
输出最后剩下的牌的序号;
思路:
将牌按照强度排列,从后往前遍历,记录当前最小的强度s
和最少费用c
:
- 对于相同强度的牌,并不满足题目条件;
- 对于强度小于
s
且费用大于c
的牌,则需要丢弃;
倒序遍历保证了当前遍历的牌的强度一定小于或等于后面牌的强度,只需要比较费用即可
static class Pair {
int strength, cost, idx;
public Pair(int s, int c, int idx) {
this.idx = idx;
strength = s;
cost = c;
}
}
static void solve() throws IOException {
int n = pInt();
Pair[] pairs = new Pair[n];
for (int i = 0; i < n; i++) {
String[] ins = pStringArray();
pairs[i] = new Pair(pInt(ins[0]), pInt(ins[1]), i + 1);
}
Arrays.sort(pairs, (a, b) -> {
if (a.strength == b.strength) return b.cost - a.cost;
return a.strength - b.strength;
});
int s = Integer.MAX_VALUE, c = Integer.MAX_VALUE;
List<Integer> ans = new ArrayList<>();
for (int i = n - 1; i >= 0; i--) {
if (!(pairs[i].strength < s && pairs[i].cost > c)) {
ans.add(pairs[i].idx);
}
s = Math.min(s, pairs[i].strength);
c = Math.min(c, pairs[i].cost);
}
ans.sort(Comparator.comparingInt(a -> a));
out.println(ans.size());
for (int x : ans) out.print(x + " ");
}
D - AtCoder Wallpaper
题目:
给一个二维坐标平面,将其按以下条件划分:
- x = n
- y = n (n为偶数)
- x + y = n (n为偶数)
相邻的两块区域需要是不同的颜色,包含 (0.5, 0.5)的区域需要涂成黑色(下面为题目示例图)
思路:
观察图形的规律,可以发现X轴隔4重复,Y轴隔2重复,那么可以通过将所求矩阵平移到第一象限通过前缀和求解;
static final int[][] t = new int[5][3];
static {
t[1][1] = 2;
t[2][1] = 3;
t[3][1] = 3;
t[4][1] = 4;
t[1][2] = 3;
t[2][2] = 6;
t[3][2] = 7;
t[4][2] = 8;
}
static void solve() throws IOException {
int[] ins = pIntArray(0);
for (int i = 0; i < ins.length; i ++) {
ins[i] += (int) 1e9;
}
int a = ins[0], b = ins[1], c = ins[2], d = ins[3];
out.println(cal(c, d) + cal(a, b) - cal(c, b) - cal(a, d));
}
static long cal(long x, long y) {
long hd = x / 4, vd = y / 2;
int hm = (int) (x % 4), vm = (int) (y % 2);
long ans = hd * vd * 8;
ans += vd * t[hm][2];
ans += hd * t[4][vm];
ans += t[hm][vm];
return ans;
}
E - Remove Pairs
题目:
有N张牌,每张牌前面和背面都写上数字,放置在桌面上,A和B每次取两张前面数字相同或者背面数字相同的牌并移除;
A先手,如果有一方没有牌可以移除了则输掉,输出胜利的一方;
思路:
双方采用最优策略,对于A来说,只要能赢一次就是A获胜,反之如果A无论如何都无法获胜,那么B获胜;
同时题目的N<=18;最多也就只有218种状态,可以通过枚举每一种状态,判断当前状态能够从上一种状态转移而来;
这里状态定义为在本回合中A是否能够移除两张牌,用二进制表示牌是否已经被移除:1表示未移除的牌,0表示已经移除的牌;
那最终状态 2N-1 就是在一开始能否有机会获胜;
static void solve() throws IOException {
int n = pInt();
int[] a = new int[n], b = new int[n];
for (int i = 0; i < n; i++) {
String[] ins = pStringArray();
a[i] = pInt(ins[0]);
b[i] = pInt(ins[1]);
}
int max = 1 << 18;
boolean[] dp = new boolean[max];
for (int k = 0; k < max; k++) {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((a[i] == a[j] || b[i] == b[j]) && ((k >> i & 1) == 1) && ((k >> j & 1) == 1)) {
dp[k] |= !dp[k ^ (1 << i) ^ (1 << j)];
}
}
}
}
if (dp[max - 1]) out.print("Takahashi");
else out.print("Aoki");
}
模板代码
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Example {
static void solve() throws IOException {
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
static {
try {
is = Files.newInputStream(Paths.get("F:\\Notes\\Algorithm\\Problems\\java\\java\\src\\main\\java\\input.txt"));
} catch (Exception e) {
is = System.in;
}
}
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static int pInt() throws IOException {return Integer.parseInt(in.readLine());}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static long pLong() throws IOException {return Long.parseLong(in.readLine());}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
private static long[] pLongArray(int start) throws IOException {
String[] s = pStringArray();
long[] arr = new long[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Long.parseLong(s[j]);
}
return arr;
}
}