Atcoder Begginer Contest 354A~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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值