置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年9月2日 星期三

ZeroJudge 解題筆記:s216.三仙鬥法 (Competition)

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


ZeroJudge 題目連結:s216.三仙鬥法 (Competition)

題目 pdf 檔連結:三仙鬥法 (Competition)

解題想法


題目是多筆測資。每筆測資第一列是一個整數 $R$,代表共有 $R$ 輪比賽;第二列有 3 個正整數 $a, b, c ~(1 \leq a, b, c \leq 10^{18})$,代表 3 個學院派出的選手靈氣值。每回合行動時,靈氣值最低的選手恢復 1 點靈氣值,較高的 2 個選手各減 1 點靈氣值;如果有多個選手的靈氣值最低,每個選手皆有相同的機率恢復 1 點靈氣值;不斷執行直到同時有 2 個選手的靈氣值歸零,此時靈氣值還沒有歸零的選手獲勝。題目要回傳每回合獲勝選手代表的學院,A、B、C 其中一個字母;如果三個學院獲勝機率相等,回傳 A B C。

由於這題的靈氣值很大,如果真的模擬比賽過程一定會超時,要找數學規律解題。由於 3 個選手其中 2 個的靈氣值減 1,另 1 個選手靈氣值加 1,所有選手的靈氣值都會加 1 或減 1。如果其中 2 個選手的靈氣值為來是偶數、另 1 個選手的靈氣值原為奇數,經過 1 個回合之後 2 個人的靈氣值同時變為奇數、另 1 個人的靈氣值變為偶數,因此只有這 2 個人的靈氣值同時歸零才會結束這輪比賽,一定是另 1 個選手獲勝。如果 3 個選手的靈氣值皆為偶數或奇數,經過多個回合之後 3 個人的靈氣值會相等,獲勝機率相同,答案是 A B C。因此這題不需要模擬比賽過程,只要用 $a, b, c$ 的奇偶性就可以直接輸出答案。

Python 程式碼


使用時間約為 0.1 s,記憶體約為 11.4 MB,通過測試。
def solve():
    import sys
    
    def get_tokens():
        for line in sys.stdin:
            for token in line.split():
                yield int(token)
    
    tokens = get_tokens()
    result = []
    while True:
        try:
            R = next(tokens)
        except StopIteration:
            break
        
        for _ in range(R):
            a = next(tokens) % 2
            b = next(tokens) % 2
            c = next(tokens) % 2
            if a == b == c:
                result.append("A B C\n")
            elif b == c:
                result.append("A\n")
            elif a == c:
                result.append("B\n")
            elif a == b:
                result.append("C\n")
        
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


C++ 程式碼


$a, b, c$ 要用 long long 避免溢位,使用時間約為 48 ms,記憶體約為 1.6 MB,通過測試。
#include <cstdio>

int main() {
    int R;
    while(scanf("%d", &R) != EOF) {
        long long a, b, c;
        for(int r = 0; r < R; r++) {
            scanf("%lld %lld %lld", &a, &b, &c);
            a %= 2; b %= 2; c %= 2;
            if (a == b && b == c) {
                puts("A B C");
            } else if (a == b) {
                puts("C");
            } else if (b == c) {
                puts("A");
            } else if (a == c) {
                puts("B");
            }
        }
    }
    return 0;
}

C 語言程式碼


$a, b, c$ 要用 long long 避免溢位,使用時間約為 50 ms,記憶體約為 1.6 MB,通過測試。
#include <stdio.h>

int main() {
    int R;
    while(scanf("%d", &R) != EOF) {
        long long a, b, c;
        for(int r = 0; r < R; r++) {
            scanf("%lld %lld %lld", &a, &b, &c);
            a %= 2; b %= 2; c %= 2;
            if (a == b && b == c) {
                puts("A B C");
            } else if (a == b) {
                puts("C");
            } else if (b == c) {
                puts("A");
            } else if (a == c) {
                puts("B");
            }
        }
    }
    return 0;
}

沒有留言:

張貼留言