AtCoder Beginner Contest 327 题解 A-D

目录

  • A - ab
  • B - A^A
  • C - Number Place
  • D - Good Tuple Problem

A - ab

原题链接

题目描述
判断一个给定的字符串是否存在字符a和字符b相邻。

public static void solve() throws IOException{
    int a = readInt();
    String s = readString();
    boolean f = s.contains("ab") || s.contains("ba");
    printWriter.println(f ? "Yes" : "No");
}

B - A^A

原题链接

题目描述
给定一个整数B,判断是否存在一个整数A,使得 A A = B A^A=B AA=B,如果存在,输出 A A A,否则输出 − 1 -1 1

思路:枚举

public static void solve() throws IOException{
    long a = readLong();
    boolean f = false;
    for (int i = 1; i <= 100; i++) {
        long q = 1;
        for (int j = 1; j <= i; j++) {
            q *= i;
        }
        if (q == a) {
            printWriter.println(i);
            f = true;
            break;
        }
        if (q > a) break;
    }
    if (!f) {
        printWriter.println(-1);
    }
}

C - Number Place

原题链接

题目描述
给定义一个 9 × 9 9 \times 9 9×9 的二维矩阵,判断这个矩阵是否满足以下全部条件,如果满足输出Yes,否则输出No

  • 1 ∼ 9 1 \sim 9 19的数字分别都在每行每列出现一次。
  • 将该二维矩阵按顺序拆为 9 9 9 3 × 3 3 \times 3 3×3 的二维矩阵后, 1 ∼ 9 1 \sim 9 19的数字分别都在每个矩阵出现一次。

思路:模拟+技巧

  • 先判断每行每列是否满足条件。
  • 再判断每个小二维矩阵是否满足条件。
public static void solve() throws IOException{
    int[][] map = utils.nextIntArray(9, 9);
    boolean f = true;
    // 判断行
    n = 9;
    for (int i = 1; i <= n; i++) {
        Set<Integer> set = new HashSet<>();
        for (int j = 1; j <= n; j++) {
            set.add(map[i][j]);
        }
        if (set.size() != 9) f = false;
    }
    // 判断列
    for (int i = 1; i <= n; i++) {
        Set<Integer> set = new HashSet<>();
        for (int j = 1; j <= n; j++) {
            set.add(map[j][i]);
        }
        if (set.size() != 9) f = false;
    }
    // 判断小圈
    int[] x = new int[] {1, 4, 7}, y = new int[] {3, 6, 9};
    for (int a = 0; a < 3; a++) {// 控制行
        for (int b = 0; b < 3; b++) {// 控制列
            Set<Integer> set = new HashSet<>();
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                	// 处于该小圈范围内
                    if (i >= x[a] && i <= y[a] && j >= x[b] && j <= y[b]) {
                        set.add(map[i][j]);
                    }
                }
            }
            if (set.size() != 9) {
                f = false;
                break;
            }
        }
    }
    printWriter.println(f ? "Yes" : "No");
}

D - Good Tuple Problem

原题链接

题目描述
给定一个数组 S S S 和一个数组 T T T,长度都为 M M M。问是否存在一个长度为 N N N01 数组 X X X,使得 X S i ≠ X T i ( 1 ≤ i ≤ N ) X_{S_i} \neq X_{T_i}(1 \leq i \leq N) XSi=XTi(1iN),如果存在,输出 Yes,否则输出 No

输入样例

3 3
1 2 3
2 3 1

输出样例

No

思路:并查集+技巧

  • 这题仅问我们是否存在,而不要求求出序列 X X X,那么可以使用并查集,将 X X X 存在矛盾的两个位置记录下来,关键在于怎么维护存在矛盾的两个位置。
  • 使用 N N N作为偏移量,每遍历到一对 S i S_i Si T i T_i Ti 时,可以理解为都是在染色。
    ① 如果 p [ S i ] ≠ p [ T i ] p[S_i] \neq p[T_i] p[Si]=p[Ti],那么就分别更新他们的父节点为 f i n d ( T i + n ) find(T_i + n) find(Ti+n) f i n d ( S i + n ) find(S_i + n) find(Si+n),表示 S i S_i Si不能和 f i n d ( T i + n ) find(T_i + n) find(Ti+n)染同一种颜色, T i T_i Ti不能和 f i n d ( S i + n ) find(S_i + n) find(Si+n)染同一种颜色。
    ② 如果 p [ S i ] = p [ T i ] p[S_i] = p[T_i] p[Si]=p[Ti],假设为 p p p,此时 S i S_i Si 不能和 p p p 染同一种颜色, T i T_i Ti不能和 p p p 染同一种颜色,但是 S i S_i Si 又不能和 T i T_i Ti 染同一种颜色,但是总共又只能染两种颜色,这时就出现了矛盾。
static int[] p;

public static void solve() throws IOException{
    int n = readInt(), m = readInt();
    int[] s = new int[m + 1], t = new int[m + 1];
    for (int i = 1; i <= m; i++) s[i] = readInt();
    for (int i = 1; i <= m; i++) t[i] = readInt();
    p = new int[2 * n + 1];
    for (int i = 1; i <= 2 * n; i++) p[i] = i;
    boolean f = true;
    for (int i = 1; i <= m; i++) {
        int a = s[i], b = t[i];
        int pa = find(a), pb = find(b);
        if (pa == pb) {// 出现矛盾
            f = false;
            break;
        }
        p[pa] = find(b + n);
        p[pb] = find(a + n);
    }
    printWriter.println(f ? "Yes" : "No");
}

public static int find(int x) {
    if (x != p[x]) {
        p[x] = find(p[x]);
    }
    return p[x];
}

你可能感兴趣的:(模拟,并查集,技巧题,算法)