Atcoder Beginner Contest 346 A~E题解

本文介绍了AtCoderBeginnerABC346比赛中的四个问题,涉及整数乘积计算、字符串子串查找、整数序列求和、字符替换成本最小化和矩阵颜色计数,展示了用Java编程解决这些技术问题的方法。
摘要由CSDN通过智能技术生成

A - Adjacent Product

题目:
给N个数字 A1 到 AN,定义 Bi = Bi-1 x Bi,按顺序输出 B1 到 BN-1

思路:
直接模拟

package atcoder.beginner.abc346;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

public class A {

    static void solve() throws IOException {
        int n = pInt(in.readLine());
        int[] a = pIntArray(0);
        for (int i = 0 ; i < n - 1; i ++) out.print(a[i] * a[i + 1] + " ");
    }

    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;
    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 long pLong(String s) {
        return Long.parseLong(s);
    }
    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;
    }
}


B - Piano

题目:
定义字符串 swbwbwwbwbwbw 无限次重复,判断是否存在子串包含 Ww 字符 和 Bb 字符

思路:
题目所给的 W 和 B 加起来最多为 200,那只需要重复上面的字符串到达 400 长度即可;
然后使用 滑动窗口 统计区间内的字符出现次数,满足题目要求就输出 Yes

package atcoder.beginner.abc346;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

public class B {

    static void solve() throws IOException {
        StringBuilder sb = new StringBuilder();
        String s = "wbwbwwbwbwbw";
        int n = s.length(), repeat = 0;
        while (repeat <= 400) {
            sb.append(s);
            repeat += n;
        }
        String[] ins = pStringArray();
        int w = pInt(ins[0]), b = pInt(ins[1]);
        int l = 0, r = w + b - 1, wCnt = 0, bCnt = 0;
        for (int i = l; i <= r; i ++) {
            if (sb.charAt(i) == 'w') {
                wCnt ++;
            } else {
                bCnt ++;
            }
        }
        while (r < sb.length()) {
            if (w == wCnt && b == bCnt) {
                out.println("Yes");
                return;
            }
            l ++;
            r ++;
            if (r == sb.length()) {
                break;
            }
            if (sb.charAt(l - 1) == 'w') {
                wCnt --;
            } else {
                bCnt --;
            }
            if (sb.charAt(r) == 'w') {
                wCnt ++;
            } else {
                bCnt ++;
            }
        }
        out.println("No");

    }

    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;
    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 long pLong(String s) {
        return Long.parseLong(s);
    }
    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;
    }
}


C - Σ

题目:
给一个整数 K,以及 N 个整数的序列 A,输出从1到 K 中不包含在 A 序列中的整数总和

思路:
K很大,而N比较小,可以先计算 1 到 K 的所有数总和 ( 1 + K ) ⋅ K 2 \frac{(1 + K) \cdot K}{2} 2(1+K)K,然后用集合维护A序列,只有在集合中先前没出现的整数才减去

package atcoder.beginner.abc346;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;

public class C {

    static void solve() throws IOException {
        String[] ins = pStringArray();
        long n = pLong(ins[0]), k = pLong(ins[1]);
        long ans = (1L + k) * k / 2;
        Set<Long> st = new HashSet<>();
        ins = pStringArray();
        for (int i = 0; i < n; i ++) {
            long x = pLong(ins[i]);
            if (x > k) continue;
            if (!st.contains(x)) {
                st.add(x);
                ans -= x;
            }
        }
        out.println(ans);
    }

    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;
    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 long pLong(String s) {
        return Long.parseLong(s);
    }
    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;
    }
}


D - Gomamayo Sequence

题目:
给一个长度为 N 且仅由 01 组成的的字符串 s,如果只有一对相邻字符对相同那么称该字符串为 好字符串
对于每个 1 ≤ i ≤ N 1\le i \le N 1iN,可以选择将位置 i 的字符最多取反一次(1变成0,0变成1), 执行操作需要花费 c o s t i cost_i costi ,求将该字符串变成好字符串所需要的最小花费。

思路:
只有一对相邻字符对相同,那么意味着其他部分的字符串为 0110 交替;
假设 ii+1 位置字符相同,

  • 前面部分可能为 10101.. 或者 01010...
  • 后面部分可能为 ...10101 或者 ...01010

可以统计每个位置前部分和后面部分转换成 01 交替或者 10 交替的字符串的花费值,然后枚举所有位置,答案为前面部分的花费值加上后面部分的花费值;

package atcoder.beginner.abc346;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

public class D {

    static void solve() throws IOException {
        int n = pInt(in.readLine());
        String s = in.readLine();
        int[] cost = pIntArray(0);
        // pre0: 0101...    pre1:1010...
        long[] pre0 = new long[n + 1], pre1 = new long[n + 1];
        // suf0: ...1010   suf1: ...0101
        long[] suf0 = new long[n + 1], suf1 = new long[n + 1];

        for (int i = 0; i < n; i ++) {
            pre0[i + 1] = pre0[i];
            pre1[i + 1] = pre1[i];
            if (i % 2 == 0) {
                if (s.charAt(i) == '0') {
                    pre1[i + 1] += cost[i];
                } else {
                    pre0[i + 1] += cost[i];
                }
            } else {
                if (s.charAt(i) == '0') {
                    pre0[i + 1] += cost[i];
                } else {
                    pre1[i + 1] += cost[i];
                }
            }
        }
        for (int i = n - 1; i >= 0; i --) {
            suf0[i] = suf0[i + 1];
            suf1[i] = suf1[i + 1];
            if (i % 2 == 0) {
                if (s.charAt(i) == '0') {
                    suf0[i] += cost[i];
                } else {
                    suf1[i] += cost[i];
                }
            } else {
                if (s.charAt(i) == '0') {
                    suf1[i] += cost[i];
                } else {
                    suf0[i] += cost[i];
                }
            }
        }
        long ans = Long.MAX_VALUE;
        for (int i = 1; i < n; i ++) {
            ans = Math.min(ans, Math.min(pre0[i] + suf0[i], pre1[i] + suf1[i]));
        }
        out.println(ans);
    }

    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;
    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 long pLong(String s) {
        return Long.parseLong(s);
    }
    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;
    }
}


E - Paint

题目:
H ⋅ W H \cdot W HW 的矩阵,每个单元格最开始被涂上颜色 0,执行 M 次操作:

  • T1 == 1 给矩阵的第 Ai 行涂上颜色 Xi
  • T2 == 2 给矩阵的第 Ai 行涂上颜色 Xi

执行完上述操作后,输出所有颜色的出现次数

思路:
越早涂上去的颜色很可能会被后面的操作被覆盖,而后面涂上去的颜色不会被前面的操作覆盖
因此可以将操作倒序执行,最开始矩阵上没有涂上颜色(设为-1),越靠后的操作实际上是给对应行/列涂上颜色,比该操作靠前的操作并不会覆盖该操作;
只需要统计每行/列被涂上颜色的数量,就能计算出每次涂上对应颜色的单元格数量;
最后还需要将 0 统计上去。

package atcoder.beginner.abc346;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

public class E {

    static void solve() throws IOException {
        String[] ins = pStringArray();
        int H = pInt(ins[0]), W = pInt(ins[1]), M = pInt(ins[2]);
        Map<Integer, Long> count = new HashMap<>();

        boolean[] row = new boolean[H + 1], col = new boolean[W + 1];
        // 操作数组,需要逆序遍历,因此要记录下来
        int[][] ops = new int[M][3];
        for (int i = 0; i < M; i ++) {
            ins = pStringArray();
            for (int j = 0; j < 3; j ++) {
                ops[i][j] = pInt(ins[j]);
            }
        }
        // 统计已经被上色的行列数量
        int colCnt = 0, rowCnt = 0;
        for (int i = M - 1; i >= 0; i --) {
            int t = ops[i][0], a = ops[i][1], x = ops[i][2];
            if (t == 1) {
                if (!row[a]) {
                    row[a] = true;
                    rowCnt ++;
                    int finalColCnt = colCnt;
                    count.compute(x, (key, value) -> {
                        // 一行的单元格数量W - 已经被上色的列数量
                        long v = (value == null ? 0 : value) + W - finalColCnt;
                        return v == 0 ? null : v;
                    });
                }
            } else {
                if (!col[a]) {
                    col[a] = true;
                    colCnt ++;
                    int finalRowCnt = rowCnt;
                    count.compute(x, (key, value) -> {
                        // 一列的单元格数量H - 已经被上色的行数量
                        long v = (value == null ? 0 : value) + H - finalRowCnt;
                        return v == 0 ? null : v;
                    });
                }
            }
        }
        // 统计 0 的个数
        long sum = (long) H * W;
        for (long value : count.values()) {
            sum -= value;
        }
        if (sum != 0) {
            count.put(0, count.getOrDefault(0, 0L) + sum);
        }
        out.println(count.size());
        Map.Entry<Integer, Long>[] arr = new Map.Entry[count.size()];
        count.entrySet().toArray(arr);
        Arrays.sort(arr, Comparator.comparingLong(o -> o.getKey()));
        for (int i = 0; i < arr.length; i ++) {
            out.println(arr[i].getKey() + " " + arr[i].getValue());
        }
    }

    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;
    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 long pLong(String s) {
        return Long.parseLong(s);
    }
    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;
    }
}

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值