記事一覧に戻る
競技プログラミング
2026年5月2日

ABC456 (Promotion of AtCoder Career Design DAY)参加録

結構実装が大変な回だった気がした。
今回もDまではすんなりいけ、Eも方針は思いついたものの実装しきれず。

A: Dice

3未満、19以上の目はサイコロ3つの和では実現できない。

def solve():
    input = sys.stdin.readline 
    X = int(input())
    if 3 <= X <= 18: print("Yes")
    else: print("No")

    return 0

B: 456

ゴリラ実装。
B問題なので。
6^3通りの出目のうち、(4, 5, 6)の組み合わせとなる出目の数を求める。

def solve():
    input = sys.stdin.readline 
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    C = list(map(int, input().split()))
    total = 0
    # 4, 5, 6
    total += A.count(4) * B.count(5) * C.count(6)
    # 4, 6, 5
    total += A.count(4) * B.count(6) * C.count(5)
    # 5, 4, 6
    total += A.count(5) * B.count(4) * C.count(6)
    # 5, 6, 4
    total += A.count(5) * B.count(6) * C.count(4)
    # 6, 4, 5
    total += A.count(6) * B.count(4) * C.count(5)
    # 6, 5, 4
    total += A.count(6) * B.count(5) * C.count(4)

    print(total / (6 * 6 * 6))

    return 0

C: Not Adjacent

同じ文字が連続しない区間を伸ばせるだけ伸ばすと、その区間内でとれる全ての区間は条件を満たす。
あらかじめLまでの三角数を求めておくことで高速に計算できる。
変数名がfactorialになっているのは最初三角数ではなく階乗を計算してしまっていたため(苦笑)

def solve():
    input = sys.stdin.readline 
    S = input().strip("\n")
    count = 0
    mod = 998244353
    pre = ""
    left = 0
    L = len(S)
    factorial = [1] * (L + 1)
    for i in range(2, L+1):
        factorial[i] = (i + factorial[i-1]) % mod

    while left < L:
        right = left
        while right < L and S[right] != pre:
            pre = S[right]
            right += 1
        # print(f"Right: {right}, Left: {left}")
        count += factorial[right - left]
        pre = ""
        left = right
        
    print(count)

    return 0

D: Not Adjacent 2

DPでi番目時点での最後に使った文字毎に何通りあるのかを管理する。
i番目の文字を使う場合/使わない場合を考える。

def solve():
    input = sys.stdin.readline 
    S = input().strip("\n")
    L = len(S)
    mod = 998244353
    D = {"a": 0, "b": 1, "c": 2}
    DP = [[0, 0, 0] for _ in range(L)]
    init = D[S[0]]
    DP[0][init] = 1
    for i in range(1, L):
        s = S[i]
        idx = D[s]
        # 初めて使う
        DP[i][idx] = 1

        for j in range(3):
            # この文字を使う場合
            if j != idx:
                DP[i][idx] = (DP[i][idx] + DP[i-1][j]) % mod

            # この文字を使わない場合
            DP[i][j] = (DP[i][j] + DP[i-1][j]) % mod
    
    print(sum(DP[L-1]) % mod)

    return 0

E: Endless Holidays

ある都市にいるときに移動できる都市は次の日休日の都市のみなので、w曜日における移動経路を管理しておき、N都市 * W曜日を頂点とするグラフにおけるループ検出ができるとよい。
データの保持の仕方やらループ検出方法やらで実装に時間がかかり、方針は思いついたものの時間内に提出できなかった...

def solve():
    input = sys.stdin.readline 
    T = int(input())
    ans = ["No" for _ in range(T)]
    for t in range(T):
        N, M = map(int, input().split())
        E =[[] for _ in range(N)]
        for i in range(M):
            u, v = map(int, input().split())
            E[u-1].append(v-1)
            E[v-1].append(u-1)

        W = int(input())
        WN = [[] for _ in range(W)]
        WE = [[[] for n in range(N)] for _ in range(W)]

        S = [input().strip("\n") for _ in range(N)]
        for i, s in enumerate(S):
            for j in range(W):
                if s[j] == "o":
                    WN[j].append(i)
        for i, e in enumerate(E):
            ns = S[i]
            for ne in e:
                s = S[ne]
                for w in range(W):
                    if ns[w] == "o" and s[(w+1)%W] == "o":
                        WE[w][i].append(ne)
        
        
        def dfs(w, n, VD, FD):
            cycle = False
            VD[(w, n)] = True
            nd = (w+1)%W
            nes = WE[w][n]
            if S[n][nd] == "o":
                nes.append(n)
            
            for ne in nes:
                if not VD[(nd, ne)]:
                    cycle |= dfs(nd, ne, VD, FD)
                elif not FD[(nd, ne)]:
                    cycle = True
            FD[(w, n)] = True
            return cycle

        VD = {}
        FD = {}
        for w, nodes in enumerate(WN):
            for n in nodes:
                VD[(w, n)] = False
                FD[(w, n)] = False
        
        for n in WN[0]:
            if not VD[(0, n)]:
                if dfs(0, n, VD, FD):
                    ans[t] = "Yes"
                    break
        else:
            ans[t] = "No"

    
    print(*ans, sep="\n")


    return 0

午前の特売所

特売アールグレーの個人ブログ。
技術・趣味・備忘録など、日々の記録を発信しています。

リンク

© 2026 特売アールグレー. All rights reserved.