熱門文章

2026年5月5日 星期二

ZeroJudge 解題筆記:a271. 彩色蘿蔔

作者:王一哲
日期:2026年5月5日


ZeroJudge 題目連結:a271. 彩色蘿蔔

解題想法


首先要排除特例,也就是進食資料是空行的狀況,直接輸出原體重就好。接下來依序讀取每天的進食資料,要先結算中毒造成的效果,由於題目有說毒素會累積,假設目前累積的毒素為 $p$,則每天會使體重減少 $n \times p$,再檢查此時體重 $m$ 是否已經歸零,如果歸零則印出 bye~Rabbit 並中止迴圈。接下來結算進食的效果,依照蘿蔔的種類更新體重,如果吃到黃、黑蘿蔔會減少體重,要再檢查體重 $m$ 是否已經歸零,如果歸零則印出 bye~Rabbit 並中止迴圈。更新完每天的體重之後,如果 $m$ 還沒有歸零,則印出 $m$。

Python 程式碼


使用時間約為 1.8 s,記憶體約為 8.4 MB,通過測試。
T = int(input())
for _ in range(T):
    # 前 4 項為紅、白、黃、黑蘿蔔對應的體重變化
    # n 為中毒狀態每天減少的體重,m 為體重初始值
    x, y, z, w, n, m = map(int, input().split())
    line = input()  # 每天吃的蘿蔔
    if not line:  # 特例,沒有吃蘿蔔,直接輸出原體重
        print(f"{m:d}g")
        continue
    
    p = 0  # 累積的毒素
    for v in map(int, line.split()):  # 每天吃的蘿蔔種類
        # 要先結算中毒造成的效果
        if p > 0:
            m -= n*p
            if m <= 0:
                print("bye~Rabbit")
                break
        # 再結算進食的效果
        if v == 0:  # 沒吃
            pass
        elif v == 1:  # 紅色
            m += x
        elif v == 2:  # 白色
            m += y
        elif v == 3:  # 黃色
            m -= z
            if m <= 0:
                print("bye~Rabbit")
                break
        elif v == 4:  # 黑色
            m -= w
            p += 1  # 毒素加 1
            if m <= 0:
                print("bye~Rabbit")
                break
    # 如果 m 沒有歸零,輸出 m 的值
    if m > 0:
        print(f"{m:d}g")

2026年5月4日 星期一

ZeroJudge 解題筆記:d221. 10954 - Add All

作者:王一哲
日期:2026年5月4日


ZeroJudge 題目連結:d221. 10954 - Add All

解題想法


用最小優先佇列 pq 儲存數字,每次取出其中最小的兩個數字 a、b,a、b 相加為 c,更新成本 cost 之後再將 c 存回 pq,直到 pq 之中只剩下一個數字為止。如果用 C++ 解題要用 long long 儲存答案,用 int 會溢位。

Python 程式碼


使用時間約為 99 ms,記憶體約為 13.6 MB,通過測試。
def solve():
    import sys, heapq

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    while ptr < len(data):
        n = int(data[ptr])
        ptr += 1
        if n == 0: break
        pq = []
        for _ in range(n):
            x = int(data[ptr])
            ptr += 1
            heapq.heappush(pq, x)
        
        cost = 0
        while len(pq) >= 2:
            a = heapq.heappop(pq)
            b = heapq.heappop(pq)
            c = a + b
            cost += c
            heapq.heappush(pq, c)
        result.append(f"{cost:d}\n")
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


2026年5月3日 星期日

ZeroJudge 解題筆記:d219. 00374 - Big Mod

作者:王一哲
日期:2026年5月3日


ZeroJudge 題目連結:d219. 00374 - Big Mod

解題想法


這題的題目敘述有問題,實際上要求的是 $$ R = B^P \pmod M $$ 這題的範例測資是 b、p、m 分成 3 行,但實際的測資是 3 個數在同一行並用空格分隔,用 Python 解題的話建議用 data = sys.stdin.read().split() 一次讀取所有測資並分割,再用索引值從 data 讀取資料會比較方便。 這題想要考快速冪,並在計算次方時取模。由於 Python 的 pow 內建這樣的功能,可以直接使用,語法為
pow(底數, 次方, 模數)
如果用 C++ 解題的話要自己寫。

Python 程式碼


使用時間約為 37 ms,記憶體約為 11.1 MB,通過測試。
def solve():
    import sys

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    while ptr < len(data):
        b = int(data[ptr])
        p = int(data[ptr+1])
        m = int(data[ptr+2])
        ptr += 3
        result.append(f"{pow(b, p, m):d}\n")
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


2026年5月2日 星期六

ZeroJudge 解題筆記:d217. 00489 - Hangman Judge

作者:王一哲
日期:2026年5月2日


ZeroJudge 題目連結:d217. 00489 - Hangman Judge

解題想法


用字典 $state$ 記錄答案中每個字元是否被猜中,為了在檢查時比較好寫,我將還沒有被猜中的字元狀態標記成 True。再用另一個字典 $used$ 記錄已經猜過的字元。接下來依序讀取猜測字串的每個字元,檢查這個字元是否是答案、是否已經猜過,計算猜對的字元數量及猜錯的次數。最後依照猜對的字元數量及猜錯的次數輸出對應的答案。

Python 程式碼


使用時間約為 16 ms,記憶體約為 8.6 MB,通過測試。
def solve():
    import sys

    result = []  # 輸出的內容
    data = sys.stdin.read().split()
    ptr = 0
    while ptr < len(data):
        n = int(data[ptr])  # 編號
        ptr += 1
        if n == -1: break  # 中止迴圈
        result.append(f"Round {n:d}\n")
        ans = data[ptr]  # 答案
        ptr += 1
        state = {c: True for c in ans}  # 答案中各字母狀態,True 為還沒有猜中
        guess = data[ptr]  # 猜測的字串
        ptr += 1
        m, cnt, fails = len(state), 0, 0  # 答案共有 m 個相異字母,猜中 cnt 個,猜錯 fails 次
        used = dict()  # 已經猜過的字母
        """ 檢查是否過關 """
        for c in guess:  # 依序由 guess 讀取字母 c
            if c not in state:  # 如果 c 不在 state 之中
                if c not in used:  # 如果 c 不在 used 之中
                    fails += 1  # 新的猜錯字母,fails 加 1
                    if fails == 7:  break  # 猜錯 7 次,失敗,中止迴圈
            elif state[c]:  # 如果 c 在 state 之中而且 c 還沒有被猜中
                state[c] = False  # 設定為 False
                cnt += 1  # 猜中數量加 1
                if cnt == m: break  # 全部猜中,過關,中止迴圈
            used[c] = True  # c 加入 used
        """ 判斷答案 """
        if fails == 7:  # 失敗
            result.append("You lose.\n")
        else:
            if cnt == m:  # 過關
                result.append("You win.\n")
            else:  # 中離
                result.append("You chickened out.\n")
    """ 輸出答案 """
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


2026年5月1日 星期五

ZeroJudge 解題筆記:d194. 11572 - Unique Snowflakes

作者:王一哲
日期:2026年5月1日


ZeroJudge 題目連結:d194. 11572 - Unique Snowflakesd716. Unique Snowflakes(強化版)

解題想法


用滑動視窗解題,用字典 $last$ 記錄每一個編號的雪花上次出現的索引值,視窗左端點為 $left$。接下來依序讀取目前的雪花編號為 $snow$、視窗右端點為 $right$,如果 $last$ 之中有 $snow$ 而且上一次出現的索引值大於等於 $left$,要更新視窗範圍,將 $left$ 改成 $last[snow] + 1$,再將 $last[snow]$ 更新為 $right$;最後更新最大值 $imax$,取 $imax$ 及 $right - left + 1$ 較大者。

Python 程式碼


使用時間約為 0.1 s,記憶體約為 24.7 MB,通過測試。
t = int(input())  # t 筆測資
for _ in range(t):  # 執行 t 次
    n = int(input())  # n 片雪花
    snowflake = [int(input()) for _ in range(n)]  # 讀取雪花編號
    last = dict()  # 每一個編號的雪花上次出現的索引值
    imax = 0  # 不同編號雪花數量最大值
    left = 0  # 滑動視窗左端點
    for right, snow in enumerate(snowflake):  # 依序讀取雪花編號
        if snow in last and last[snow] >= left:  # 如果 snow 在 last 之中,而且索引值大於等於左端點
            left = last[snow] + 1  # 更新左端點為目前雪花編號前一次出現的索引值加 1
        last[snow] = right  # 更新目前雪花編號出現的索引值為 right
        imax = max(imax, right - left + 1)  # 更新最大值
    print(imax)

使用時間約為 55 ms,記憶體約為 37.7 MB,通過測試。如果更新 $imax$ 時不呼叫 $max$,速度會更快,使用時間約為 45 ms,記憶體約為 34.9 MB,通過測試。
def solve():
    import sys

    result = []
    data = sys.stdin.read().split()
    ptr = 1
    while ptr < len(data):
        n = int(data[ptr])  # n 片雪花
        ptr += 1
        last = dict()  # 每一個編號的雪花上次出現的索引值
        imax = 0  # 不同編號雪花數量最大值
        left = 0  # 滑動視窗左端點
        for right in range(n):  # 依序讀取雪花編號
            snow = data[ptr]
            ptr += 1
            if snow in last and last[snow] >= left:  # 如果 snow 在 last 之中,而且索引值大於等於左端點
                left = last[snow] + 1  # 更新左端點為目前雪花編號前一次出現的索引值加 1
            last[snow] = right  # 更新目前雪花編號出現的索引值為 right
            val = right - left + 1  # 更新最大值
            if val > imax: imax = val
            #imax = max(imax, right - left + 1)  
        result.append(f"{imax:d}\n")
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()