AtCoder Beginner Contest 333 题解 A-E

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。按升序排列的 repunits1,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) (1i<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) (1iN) 由一对整数 ( 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) + " ");
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值