置頂

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

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

熱門文章

2025年12月20日 星期六

ZeroJudge 解題筆記:a132. 10931 - Parity

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


ZeroJudge 題目連結:a132. 10931 - Parity

解題想法


這題要將一個 10 進位整數轉換成 2 進位字串,再計算字串中 1 的數量。如果用 Python 解題,可以直接用內建的 bin,不過轉換後的字串前面有 0b,要用切片從索引值 2 開始取子字串。如果用 C++ 解題,可以自己寫轉換用的函式,也可以引入 bitset,用 bitset 之中的 to_string() 功能轉換整數。

Python 程式碼


Python 有內建的 10 進位整數轉換成 2 進位字串函式,使用時間約為 8 ms,記憶體約為 2.9 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)
    if n == 0: break
    s = bin(n)[2:]
    p = sum([c == '1' for c in s])
    print(f"The parity of {s:s} is {p:d} (mod 2).")


C++ 程式碼


自己寫將 10 進位整數轉換成 2 進位字串的函式,使用時間約為 1 ms,記憶體約為 316 kB,通過測試。
#include <iostream>
#include <string>
using namespace std;

string bin(int n) {
    string s = "";
    while(n) {
        if (n&1) s = "1" + s;
        else s = "0" + s;
        n >>= 1;
    }
    return s;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n;
    while(cin >> n && n != 0) {
        string s = bin(n);
        int p = 0;
        for(char c : s) {
            if (c == '1') p++;
        }
        cout << "The parity of " << s << " is " << p << " (mod 2).\n";
    }
    return 0;
}

2025年12月19日 星期五

ZeroJudge 解題筆記:a133. 10066 - The Twin Towers

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


ZeroJudge 題目連結:a133. 10066 - The Twin Towers

解題想法


這題考最長共同子序列 (longest common subsequence, LCS),只要找長度,不需要找 LCS 的內容。寫法有兩種,假設兩筆資料 a、b 的長度分別為 n、m,可以用一個 $(n+1) \times (m+1)$ 的二維陣列儲存動態規劃資料,$dp[i][j]$ 代表比較到 $a[i-1]$ 與 $b[i-1]$ 時 LCS 的長度;也可以用兩個陣列儲存資料,用滾動陣列節省記憶體。

Python 程式碼


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

ca = 0
for line in sys.stdin:
    n, m = map(int, line.split())
    if n == 0 and m == 0: break
    ca += 1
    print(f"Twin Towers #{ca:d}")
    a = tuple(map(int, sys.stdin.readline().split()))
    b = tuple(map(int, sys.stdin.readline().split()))
    dp = [[0]*(m+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            if a[i-1] == b[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    print(f"Number of Tiles : {dp[-1][-1]:d}\n")


2025年12月18日 星期四

ZeroJudge 解題筆記:a131. 00739 - Soundex Indexing

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


ZeroJudge 題目連結:a131. 00739 - Soundex Indexing

解題想法


可以用陣列建立字母、數字對照表,將字母 A, B, C, ..., Z 對應的數字填入陣列之中。也可以用字典建立對照表,這個寫法比較容易閱讀。

Python 程式碼


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

table = ('0', '1', '2', '3', '0', '1', '2', '0', '0', '2',
         '2', '4', '5', '5', '0', '1', '2', '6', '2', '3',
         '0', '1', '0', '2', '0', '2')
print("         NAME                     SOUNDEX CODE")
for line in sys.stdin:
    s = line.strip()
    n = len(s)
    last = table[ord(s[0]) - ord('A')]
    result = [s[0]]
    for i in range(1, n):
        if len(result) >= 4: break
        curr = table[ord(s[i]) - ord('A')]
        if curr != '0' and curr != last: result.append(curr)
        last = curr
    while len(result) < 4: result.append('0')
    output = " "*9 + s + " "*(25-n) + "".join(result)
    print(output)
print("                   END OF OUTPUT")


2025年12月17日 星期三

ZeroJudge 解題筆記:a130. 12015 - Google is Feeling Lucky

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


ZeroJudge 題目連結:a130. 12015 - Google is Feeling Lucky

解題想法


這題考排序,網站相關度高排前面,如果相關度相同,先讀到的放前面。如果用 Python 解題,可以將網站相關度 val、讀取資料的索引值 idx、網址 url 組成 tuple 再存入串列,排序時用 lambda function 寫比較式 (-x[0], x[1])。如果用 C++ 解題,可以自訂結構體儲存網站相關度 val、讀取資料的索引值 idx、網址 url,資料存入 vector,排序時用 lambda function 寫比較式。

Python 程式碼


使用時間約為 7 ms,記憶體約為 2.9 MB,通過測試。
T = int(input())
for t in range(1, T+1):
    print(f"Case #{t:d}:")
    data = []
    for i in range(10):
        url, v = input().split()
        data.append((int(v), i, url))
    # 排序,相關度高排前面,如果相關度相同,先讀到的放前面
    data.sort(key = lambda x : (-x[0], x[1]))
    vmax = data[0][0]
    for d in data:
        if d[0] < vmax: break
        print(d[2])


2025年12月16日 星期二

ZeroJudge 解題筆記:a111. 12149 - Feynman

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


ZeroJudge 題目連結:a111. 12149 - Feynman

解題想法


如果 $n = 1$ 答案為 $1$;如果 $n = 2$,答案為 $1 + 4 = 1 + 2^2 = 5$;如果 $n = 3$,答案有邊長 3 的正方形 1 個,邊長 2 的正方形 4 個,邊長 1 的正方形 9 個,也就是 $1 + 4 + 9 = 1 + 2^2 + 3^2 = 14$。解題時可以建表或是代公式 $$ ans = \sum_{i = 1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$

Python 程式碼


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

dp = [0]*101
dp[0] = 0
dp[1] = 1
for i in range(2, 101):
    dp[i] = dp[i-1] + i*i

for line in sys.stdin:
    n = int(line)
    if n == 0: continue
    print(dp[n])

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

for line in sys.stdin:
    n = int(line)
    if n == 0: continue
    print(n*(n+1)*(2*n + 1)//6)


2025年12月15日 星期一

ZeroJudge 解題筆記:a011. 00494 - Kindergarten Counting Game

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


ZeroJudge 題目連結:a011. 00494 - Kindergarten Counting Game

解題想法


這題要讀取整行字串之後依序讀取每個字元,用變數 last 記錄目前連續出現的字母數量,如果這個字元是字母則 last 加 1; 反之,前一個單字結束了,如果 last 大於 0,單字數量 cnt 加 1,再將 last 歸零。檢查完整行字串之後,記得要再結算一次,才不會漏掉最後一個單字。

Python 程式碼


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

for line in sys.stdin:
    last, cnt = 0, 0
    for c in line.strip():
        if c.isalpha(): last += 1
        else:
            if last > 0: cnt += 1
            last = 0
    if last > 0: cnt += 1
    print(cnt)


2025年12月14日 星期日

ZeroJudge 解題筆記:o087. 王子的名字

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


ZeroJudge 題目連結:o087. 王子的名字

解題想法


先檢查讀取到的名字是否都是字母,如果有任何一個字元不是字母,分數為 -1;如果所有字元都是字母,按照題目給的規則計分。將分數、索引、名字組成 tuple 或是自訂的 struct ,存入陣列之中,最後按照分數、索引值由小到大排序。

Python 程式碼


使用時間約為 25 ms,記憶體約為 3.3 MB,通過測試。
def Evaluate(Name: str):
    if(type(Name) != str): return -1                              
    Score = 0
    NameLen = len(Name)
    for i in range(NameLen):
        CharCode = ord(Name[i])
        Score += ((CharCode * 1123) % 1002)
        while (CharCode > 0):
            Score += (CharCode % 10)
            CharCode = (CharCode // 10)
    return (Score % 101)

n = int(input())
names = []
for i in range(n):
    name = input()
    score = Evaluate(name)
    names.append((score, i, name))
names.sort()
for score, _, name in names:
    print(f"{name:s} {score:d}")


2025年12月13日 星期六

ZeroJudge 解題筆記:o067. 柯尼斯堡七橋問題

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


ZeroJudge 題目連結:o067. 柯尼斯堡七橋問題

解題想法


有奇數條邊的節點數量必須小於等於 2 才有解,可以真的存圖再計算有奇數條邊的節點數量,也可以不存圖、只儲存每個節點是否有奇數條邊。不要真的模擬走訪過程。

Python 程式碼


真的存圖,使用時間約為 0.4 s,記憶體約為 12.7 MB,通過測試。
n, m = map(int, input().split())
graph = dict()
for _ in range(m):
    u, v = map(int, input().split())
    if u not in graph: graph[u] = [v]
    else: graph[u].append(v)
    if v not in graph: graph[v] = [u]
    else: graph[v].append(u)
cnt = 0
flag = True
for v in graph.values():
    if len(v)%2 == 1: cnt += 1
    if cnt > 2:
        flag = False
        break
print("YES" if flag else "NO")

只存每個節點是否有奇數條邊,使用時間約為 0.4 s,記憶體約為 3.4 MB,通過測試。
n, m = map(int, input().split())
vertice = [False]*(n+1)
for _ in range(m):
    u, v = map(int, input().split())
    vertice[u] = not vertice[u]
    vertice[v] = not vertice[v]
cnt = sum(vertice)
print("YES" if cnt <= 2 else "NO")


2025年12月12日 星期五

ZeroJudge 解題筆記:n700. 蝸牛的踩地雷攻略 3 (點方塊)

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


ZeroJudge 題目連結:n700. 蝸牛的踩地雷攻略 3 (點方塊)

解題想法


為了不要檢查是否出界,我習慣在地圖的最右側、最下方加上用不到的符號當作哨兵。用自訂函式 count 計算周圍 8 格的地雷數量,再用另一個自訂函式 reveal 翻開格子,reveal 之中是用 BFS 找出所有可以翻開的格子,同時將翻開後的地圖儲存到另一個二維串列之中。

Python 程式碼


使用時間約為 24 ms,記憶體約為 3.8 MB,通過測試。
from collections import deque

def count(grid, r, c):  # 計算周圍 8 格的地雷數量
    cnt = 0  # 地雷數量
    for dr, dc in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):
        nr, nc = r+dr, c+dc
        if grid[nr][nc] == '*': cnt += 1
    return cnt

def reveal(grid, result, ri, ci, n, m):  # 翻開格子,代入地圖 grid,結果 result,位置 (ri, ci),維度 n*m
    visited = [[False]*(m+1) for _ in range(n+1)]  # 是否已走訪
    que = deque([(ri, ci)])  # 待走訪的位置
    visited[ri][ci] = True  # (ri, ci) 已走訪
    while que:  # 如果 que 還有資料繼續執行
        r, c = que.popleft()  # 從 que 開頭讀取並移除資料
        cnt = count(grid, r, c)  # 計算 (r, c) 周圍的地雷數量
        if cnt == 0:  # 如果周圍沒有地雷
            result[r][c] = '_'  # 翻開,是空地
            # 檢查周圍 8 格,如果還沒有出界、沒有走訪、是未翻開的格子
            for dr, dc in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):
                nr, nc = r+dr, c+dc
                if grid[nr][nc] != '@' and not visited[nr][nc] and grid[nr][nc] == '#':
                    visited[nr][nc] = True  # (nr, nc) 已走訪
                    que.append((nr, nc))  # (nr, nc) 加入 que
        else: result[r][c] = str(cnt)  # 周圍有地雷,填入地雷的數量

def main():  # 主程式
    n, m, ri, ci = map(int, input().split())  # 地圖維度 n*m,起點 (ri, ci)
    grid = [list(input().strip() + '@') for _ in range(n)]  # 最右側加上 @ 作為哨兵
    grid.append(['@']*(m+1))  # 最下方加 m+1 個 @ 作為哨兵
    result = [['#']*m for _ in range(n)]  # 儲存結果用的 n*m 二維串列
    ri -= 1; ci -= 1  # 配合索引值,ri, ci 減 1
    reveal(grid, result, ri, ci, n, m)  # 呼叫 reveal 求解
    for row in result: print("".join(row))  # 印出答案

if __name__ == '__main__':
    main()


2025年12月11日 星期四

ZeroJudge 解題筆記:n689. pD. 技能點數

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


ZeroJudge 題目連結:n689. pD. 技能點數

解題想法


我用接鄰矩陣 graph 儲存有向圖,用串列 need 儲存學習各技能所需的前置技能,用集合 learn 儲存學到的技能。將一開始拿到的技能書 book 存入待走訪佇列 que,用 BFS 找出所有可以學到的技能。

Python 程式碼


使用時間約為 29 ms,記憶體約為 4.1 MB,通過測試。
from collections import deque

n, m, k = map(int, input().split())
book = list(map(int, input().split()))
graph = [[] for _ in range(n)]
need = [set() for _ in range(n)]
for _ in range(m):
    u, v = map(int, input().split())
    graph[u].append(v)
    need[v].add(u)
for b in book: need[b].clear()
learn = set(book)
que = deque(book)
while que:
    u = que.popleft()
    for v in graph[u]:
        if u in need[v]:
            need[v].remove(u)
        if not need[v]:
            que.append(v)
            learn.add(v)
print(len(learn))