熱門文章

2025年6月19日 星期四

ZeroJudge 解題筆記:p902. 凱撒密碼 (Cipher)

作者:王一哲
日期:2025年6月19日


ZeroJudge 題目連結:p902. 凱撒密碼 (Cipher)

解題想法


用字母的 ASCII 編號平移後再除以 26 取餘數,換成平移後的字母。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    s = line.strip()  # 要加密的字串
    k = int(input())  # 位移量
    a = ""  # 儲存答案用的空字串
    for c in s:  # 從 s 依序讀取字元 c
        if c.islower():  # 如果 c 是小寫字母
            c = chr((ord(c)+k-ord('a'))%26 + ord('a'))
        elif c.isupper():  # 如果 c 是大寫字母
            c = chr((ord(c)+k-ord('A'))%26 + ord('A'))
        a += c  # a 加上 c
    print(a)


2025年6月18日 星期三

ZeroJudge 解題筆記:p901. 香料 (Spices)

作者:王一哲
日期:2025年6月18日


ZeroJudge 題目連結:p901. 香料 (Spices)

解題想法


這題用字典儲存每個編號的香料在貨架上的位置,速度較慢但程式好寫。

Python 程式碼


使用時間約為 51 ms,記憶體約為 7.1 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # n 個要找的香料
    si = list(map(int, input().split()))  # 要找的香料編號
    r, c = map(int, input().split())  # 貨架 r*c
    shelf = [list(map(int, input().split())) for _ in range(r)]  # 貨架上的香料編號
    table = dict()  # 各編號香料的位置
    for i in range(r):  # 依序掃過貨架每一格
        for j in range(c):
            table[shelf[i][j]] = (i+1, j+1)  # 題目的編號從 1 開始
    for s in si:  # 依序讀取要找的香料編號
        if s not in table: print(-1)  # 如果 s 不在 table 之中印出 -1
        else: print(*table[s])  # 反之印出編號

2025年6月17日 星期二

ZeroJudge 解題筆記:p900. 旅遊計畫 (Travel)

作者:王一哲
日期:2025年6月17日


ZeroJudge 題目連結:p900. 旅遊計畫 (Travel)

解題想法


完整地掃過 i = 0 ~ 9 天的去程費用,再掃過 j = i ~ 9 的回程費用,更新最低費用。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    going_trip = tuple(map(int, line .split()))  # 去程費用
    return_trip = tuple(map(int, input().split()))  # 回程費用
    start, end, imin = 0, 0, float('inf')  # 出發日、回程日、最低費用
    for i in range(10):  # 依序掃過 i = 0 ~ 9
        for j in range(i, 10):  # 依序掃過 j = i ~ 9
            fee = going_trip[i] + return_trip[j] + (j-i)*1000  # 費用
            if fee < imin:  # 如果是新的最低費用,更新 start, end, imin
                start, end, imin = i+1, j+1, fee
    print(start, end, imin)


2025年6月16日 星期一

ZeroJudge 解題筆記:o923. 陣列運算 (Array)

作者:王一哲
日期:2025年6月16日


ZeroJudge 題目連結:o923. 陣列運算 (Array)

解題想法


我沒有想到比較快的作法,就是依照題目的規定處理陣列 1 或 2,直到輸出是 0 為止。

Python 程式碼


使用時間約為 29 ms,記憶體約為 3.8 MB,通過測試。
import sys

for line in sys.stdin:
    a = list(map(int, line.split()))  # 陣列 1
    b = list(map(int, input().split()))  # 陣列 2
    c = 1  # 輸出的值,預設為 1
    while c:  # 當 c 不是 0,繼續執行
        if c%2 == 1:  # 如果上一輪輸出是奇數,處理陣列 1
            if a[0]%3 == 0:  # 如果 a[0] 可以被 3 整除
                imax = max(a)  # 找出陣列 1 的最大值
                print(imax)  # 印出 imax
                c = imax  # 重設輸出的值
                for i in range(5):  # 掃過 a,如果 a[i] 等於 imax 則除以 2
                    if a[i] == imax: a[i] = imax//2
            else:  # 如果 a[0] 不能被 3 整除
                imin = 10000  # 最小值,預設為超出題目範圍的值
                for x in a:  # 依序掃過 a,找非 0 的最小值
                    if 0 < x < imin: imin = x
                print(imin)  # 印出最小值
                c = imin  # 重設輸出的值
                for i in range(5):  # 掃過 a,如果 a[i] 等於 imin 則減 1
                    if a[i] == imin: a[i] = imin-1
        else:  # 如果上一輪輸出是偶數,處理陣列 2
            if b[0]%3 == 0:  # 如果 b[0] 可以被 3 整除
                imax = max(b)  # 找出陣列 2 的最大值
                print(imax)  # 印出 imax
                c = imax  # 重設輸出的值
                for i in range(5):  # 掃過 b,如果 b[i] 等於 imax 則除以 2
                    if b[i] == imax: b[i] = imax//2
            else:  # 如果 b[0] 不能被 3 整除
                imin = 10000  # 最小值,預設為超出題目範圍的值
                for x in b:  # 依序掃過 b,找非 0 的最小值
                    if 0 < x < imin: imin = x
                print(imin)  # 印出最小值
                c = imin  # 重設輸出的值
                for i in range(5):  # 掃過 b,如果 b[i] 等於 imin 則減 1
                    if b[i] == imin: b[i] = imin-1


2025年6月15日 星期日

ZeroJudge 解題筆記:o922. 年貨大街 (Market)

作者:王一哲
日期:2025年6月15日


ZeroJudge 題目連結:o922. 年貨大街 (Market)

解題想法


依序讀取商品編號及質量,計算總金額即可。

Python 程式碼


使用時間約為 30 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # n 款商品
    ps = [0] + list(map(int, input().split()))  # 各商品每公克價格,配合從1開始編號開頭加 0
    total = 0  # 總金額
    while True:  # 無窮迴圈
        x, g = map(int, input().split())  # x 商品買 g 公克
        if x == 0 and g == 0: break  # x, g 都是 0,中止迴圈
        total += ps[x]*g  # 更新 total
    print(total)

使用時間約為 25 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # n 款商品
    ps = [0] + list(map(int, input().split()))  # 各商品每公克價格,配合從1開始編號開頭加 0
    total = 0  # 總金額
    x, g = -1, -1  # x 商品買 g 公克
    while x != 0 and g != 0:  # x, g 都是 0,中止迴圈
        x, g = map(int, input().split())  # x 商品買 g 公克
        total += ps[x]*g  # 更新 total
    print(total)


2025年6月14日 星期六

ZeroJudge 解題筆記:o921. 生日快樂 (Birthday)

作者:王一哲
日期:2025年6月14日


ZeroJudge 題目連結:o921. 生日快樂 (Birthday)

解題想法


我會先將今天的日期及生日換算成從1月1日開始計算的天數,這樣在計算答案時比較方便。

Python 程式碼


使用時間約為 21 ms,記憶體約為 3.3 MB,通過測試。
import sys

month = (0, 31, 59, 90, 120, 151, 181,
         212, 243, 273, 304, 334, 365)  # 每月累計天數
for line in sys.stdin:
    m, d = map(int, line.split())  # 今天的月日
    today = month[m-1] + d  # 今天轉成從1月1日開始的天數
    mb, db = map(int, input().split())  # 生日的月日
    birthday = month[mb-1] + db  # 生日轉成從1月1日開始的天數
    print((birthday - today + 365) % 365)


2025年6月13日 星期五

ZeroJudge 解題筆記:o580. 因數計算 (Factor)

作者:王一哲
日期:2025年6月13日


ZeroJudge 題目連結:o580. 因數計算 (Factor)

解題想法


我先寫一個找因數用的函式 num_of_factor,輸入整數 x,用 set 儲存 x 的因數,最後回傳因數的數量。在主程式中,讀取要找的範圍 start、end,依序找 start 到 end 的因數數量並更新答案。

Python 程式碼


使用時間約為 67 ms,記憶體約為 3.3 MB,通過測試。
import sys

def num_of_factor(x):  # 輸入 x,找 x 的因數
    factor = {1, x}  # 因數,一定有 1, x
    for i in range(2, int(x**0.5)+1):  # 暴力解,找 i = 2 ~ sqrt(x)
        if x%i == 0:  # 如果 x 可以被 i 整除
            factor.add(i)  # i 是 x 的因數
            factor.add(x//i)  # x//i 是 x 的因數
    return len(factor)  # 回傳因數的數量

for line in sys.stdin:
    start, end = map(int, line.split())  # 要計算 start ~ end 的因數數量
    ans, imax = 0, 0  # 因數最多的數字 ans,因數數量 imax
    for i in range(start, end+1):  # 依序代入 start ~ end
        fac = num_of_factor(i)  # 呼叫 num_of_factor 計算 i 的因數數量
        if fac > imax:  # 如果 fac 大於 imax,更新 ans 及 imax
            ans = i; imax = fac
    print(ans, imax)


2025年6月12日 星期四

ZeroJudge 解題筆記:n912. 吸血鬼 (Vampire)

作者:王一哲
日期:2025年6月12日


ZeroJudge 題目連結:n912. 吸血鬼 (Vampire)

解題想法


我是用 BFS 及四方位檢查,依序更新每天獵人及吸血鬼的勢力範圍。

Python 程式碼


使用時間約為 39 ms,記憶體約為 5.6 MB,通過測試。
import sys

for line in sys.stdin:
    H, W, K = map(int, line.split())  # 地圖 H*W,K 天
    grid = [list(map(int, input().split())) + [2] for _ in range(H)]  # 地圖,每列最右側加一個 2
    grid.append([2]*(W+1))  # 最下方加一列 2
    hunter, vampire = set(), set()  # 獵人、吸血鬼位置
    for r in range(H):  # 依序掃過每一格,找出獵人、吸血鬼位置
        for c in range(W):
            if grid[r][c] == 1: hunter.add((r, c))
            elif grid[r][c] == -1: vampire.add((r, c))
    for _ in range(K):  # 執行 K 次
        ### 獵人行動回合 ###
        ht = []  # 暫存新的獵人位置
        for r, c in hunter:  # 依序讀取獵人位置
            for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):  # 四方位檢查
                nr, nc = r+dr, c+dc  # 檢查 (nr, nc)
                if grid[nr][nc] == 1 or grid[nr][nc] == 2: continue  # 如果是獵人或出界,找下一格
                grid[nr][nc] = 1  # (nr, nc) 改為 1
                ht.append((nr, nc))  # (nr, nc) 加到 ht
        for h in ht: hunter.add(h)  # 將 ht 的資料加到 hunter
        ### 吸血鬼行動回合 ###
        vt = []  # 暫存新的吸血鬼位置
        for r, c in vampire:  # 依序讀取吸血鬼位置
            for dr, dc in ((1, 1), (1, -1), (-1, -1), (-1, 1)):  # 斜向四方位檢查
                nr, nc = r+dr, c+dc  # 檢查 (nr, nc)
                if grid[nr][nc] == 0:
                    grid[nr][nc] = -1  # 如果是未佔領區域,改成 -1
                    vt.append((nr, nc))  # (nr, nc) 加到 ht
        for v in vt: vampire.add(v)  # 將 vt 的資料加到 vampire
        for h in ht:  # 將 ht 的資料從 vampire 移除
            if h in vampire: vampire.remove(h)
    for row in grid[:H]: print(*row[:W])  # 印出答案,不含最右側、最下方的 2


2025年6月11日 星期三

ZeroJudge 解題筆記:n910. 數織 (Nonogram)

作者:王一哲
日期:2025年6月11日


ZeroJudge 題目連結:n910. 數織 (Nonogram)

解題想法


先處理每欄的提示,依序讀取此欄每列的資料,計算此欄有幾個連續的 1,如果沒有任何 1 則填入 0。再處理每列的提示,依序讀取此列每欄的資料,計算此列有幾個連續的 1,如果沒有任何 1 則填入 0。

Python 程式碼


使用時間約為 1.6 s,記憶體約為 13 MB,通過測試。
import sys

for line in sys.stdin:
    N = int(line)  # 圖形 N*N
    grid = [list(map(int, input().split())) for _ in range(N)]  # 讀取地圖
    for c in range(N):  # 依序讀取每欄資料
        col = []  # 每欄提示
        cnt = 0  # 連續的 1 數量
        for r in range(N):  # 依序讀取每列資料
            if cnt != 0:  # 如果 cnt 不等於 0
                if grid[r][c] == 1: cnt += 1  # 如果 grid[r][c] 等於 1,cnt 加 1
                else:  # 如果 grid[r][c] 等於 0
                    col.append(cnt)  # 結算 cnt,將 cnt 加到 col
                    cnt = 0  # cnt 歸零
            elif grid[r][c] == 1: cnt = 1  # 如果 cnt 等於 0 而且 grid[r][c] 等於 1,cnt 設定為 1
        if cnt != 0: col.append(cnt)  # 如果 cnt 不等於 0,要再結算一次 cnt
        if col: print(*col)  # 如果 col 有資料,拆開後印出
        else: print(0)  # 如果 col 沒有資料,印出 0
    for r in range(N):  # 依序讀取每列資料
        row = []  # 每列提示
        cnt = 0  # 連續的 1 數量
        for c in range(N):  # 依序讀取每欄資料
            if cnt != 0:  # 如果 cnt 不等於 0
                if grid[r][c] == 1: cnt += 1  # 如果 grid[r][c] 等於 1,cnt 加 1
                else::  # 如果 grid[r][c] 等於 0
                    row.append(cnt)  # 結算 cnt,將 cnt 加到 col
                    cnt = 0  # cnt 歸零
            elif grid[r][c] == 1: cnt = 1  # 如果 cnt 等於 0 而且 grid[r][c] 等於 1,cnt 設定為 1
        if cnt != 0: row.append(cnt)  # 如果 cnt 不等於 0,要再結算一次 cnt
        if row: print(*row)  # 如果 row 有資料,拆開後印出
        else: print(0)  # 如果 row 沒有資料,印出 0


2025年6月10日 星期二

ZeroJudge 解題筆記:>n632. 熱門商品 (Commodity)

作者:王一哲
日期:2025年6月10日


ZeroJudge 題目連結:n632. 熱門商品 (Commodity)

解題想法


因為商品的編號不連續,用字典計數比較方便,在 Python 中可以用預設的字典,也可以用 collections 函式庫中的 defaultdict 或 Counter,由於這題要找問卷中出現最多次的商品編號,用 Counter.most_common() 最方便。在 C++ 可以用 map 或 unordered_map,因為資料不需要排序,用 unordered_map 會比較快一點。

Python 程式碼


寫法1,使用預設的 dict。使用時間約為 0.8 s,記憶體約為 78.4 MB,通過測試。
import sys

for line in sys.stdin:
    K, N = map(int, line.split())  # K 份問卷,N 家商店
    cnt = dict()  # 問卷計數器
    for i in map(int, input().split()):  # 讀取問卷資料
        if i not in cnt: cnt[i] = 1  # 如果 i 不在 cnt 之中,cnt[i] 設定為 1
        else: cnt[i] += 1  # 如果 i 在 cnt 之中,cnt[i] 加 1
    popular = max([(v, k) for k, v in cnt.items()])[1]  # 最受歡迎的商品
    _ = tuple(map(int, input().split()))  # 每家商店的商品數量,用不到
    shop, imin = 0, float('inf')  # 積分最低的商店編號及分數
    for i in range(1, N+1):  # 依序讀取 N 家商店
        score = 0  # 積分
        for j in map(int, input().split()):  # 依序讀取這家商店販賣的商品
            if j in cnt: score += cnt[j]  # 如果有出現在問卷中,分數加 cnt[j]
        if score < imin:  # 更新 shop 及 imin
            shop = i; imin = score
    print(popular, shop)  # 印出答案