置頂

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

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

熱門文章

2025年10月6日 星期一

ZeroJudge 解題筆記:f332. 貝瑞的鐵線體積

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


ZeroJudge 題目連結:f332. 貝瑞的鐵線體積

解題想法


如果函數為 $y = f(x)$,將此函數曲線以 $x$ 軸為轉軸旋轉,旋轉體體積為 $$ V = \pi \int_a^b y^2 dx $$

Python 程式碼


使用時間約為 22 ms,記憶體約為 3.4 MB,通過測試。
import math

t = int(input())  # 共 t 筆測資
for _ in range(t):  # 執行 t 次
    n = int(input())  # 多項式最高次方
    poly = list(map(int, input().split()))  # 多項式由高到低次方各項係數
    square = [0]*(2*n + 1)  # 多項式平方各項係數
    for i in range(n+1):
        for j in range(n+1):
            square[i+j] += poly[i]*poly[j]
    integral = [0]*(2*n + 1)  # 平方後積分結果,忽略常數項
    for i in range(2*n + 1):  # 計算積分式
        integral[i] = 1.0 * square[i] / (2*n + 1 - i)
    ans = 0.0  # 積分結果
    a, b = map(int, input().split())  # 積分下限、上限
    for i, c in enumerate(integral):  # 代入積分下限、上限
        ans += c * (b**(2*n + 1 - i) - a**(2*n + 1 - i))
    print(f"{math.pi*ans:.2f}")  # 印出答案時再乘以 pi


2025年10月5日 星期日

ZeroJudge 解題筆記:f291. 試算表大小

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


ZeroJudge 題目連結:f291. 試算表大小

解題想法


先將讀到的字串拆成左側字母、右側數字兩個部分,再從字母最後面往回讀取,計算是第幾欄,再將欄數乘以列數就是答案。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
s = input()  # 輸入的儲存格編號
left = ""  # 左半邊的欄位
row = 0  # 列數
for i, c in enumerate(s):  # 依序讀取 s 的字元
    if c.isdigit():  # 如果 c 是數字,取出左半邊,中止迴圈
        left = s[:i]
        row = int(s[i:])
        break
b = 1  # 計算欄位的基底
col = 0  # 欄位編號
for c in left[::-1]:  # 從 left 最後面讀取字元
    col += b*(ord(c) - ord('A') + 1)  # 計算欄位
    b *= 26  # 基底乘以 26
print(row*col)  # 答案是列、欄相乘


2025年10月4日 星期六

ZeroJudge 解題筆記:f260. 愛八卦的同學

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


ZeroJudge 題目連結:f260. 愛八卦的同學

解題想法


我用 BFS 找連通區塊數量,不過用 Python 的速度太慢,用 C++ 解題也要 0.3 s。

Python 程式碼


速度太慢,只能通過一筆測資。
import sys
from collections import deque

for line in sys.stdin:
    n, k = map(int, line.split())  # n 個人,k 組關係
    adj = [[] for _ in range(n)]  # 每個人與其它人的關係
    for _ in range(k):  # 讀取 k 行資料
        u, v = map(int, sys.stdin.readline().split())  # u, v 是朋友
        adj[u].append(v)
        adj[v].append(u)
    cnt = 0  # 小團體數量
    visited = [False]*n  # 是否已經檢查過
    for i in range(n):  # 依序讀取每一個人
        if visited[i]: continue  # 如果 i 已經檢查過,找下一個人
        visited[i] = True  # 設定為 True
        cnt += 1
        que = deque([i])
        while que:
            v = que.popleft()
            for u in adj[v]:
                if visited[u]: continue
                que.append(u)
                visited[u] = True
    print(cnt)


2025年10月3日 星期五

ZeroJudge 解題筆記:f257. 君王的處刑遊戲

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


ZeroJudge 題目連結:f257. 君王的處刑遊戲

解題想法


我是用二維陣列儲存每一個人的驚恐值,預設值為 0,-1 代表已淘汰,Python 的最右側、最下方加上 -1 當作哨兵,C++ 周圍加上 -1 當作哨兵。每次檢查位置 (x, y) 的人,如果還沒有淘汰就設定成 -1,再檢查周圍 8 格,遇到還沒有被淘汰的人就將驚恐值加 1。

Python 程式碼


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

for line in sys.stdin:
    n = int(line)  # 二維陣列 n*n
    grid = [[0]*n + [-1] for _ in range(n)]  # 最右側、最下方加 -1 當作哨兵
    grid.append([-1]*(n+1))
    k = int(sys.stdin.readline())  # 要淘汰的人數
    for _ in range(k):  # 執行 k 次
        x, y = map(int, sys.stdin.readline().split())  # 要淘汰的人位置 (y, x)
        if grid[y][x] == -1: continue  # 已淘汰,找下一個
        grid[y][x] = -1  # 已淘汰,設定成 -1
        # 搜尋四周的 8 格
        for dy, dx in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):
            ny, nx = y+dy, x+dx  # 檢查 grid[ny][nx]
            if grid[ny][nx] == -1: continue  # 已淘汰,找下一個
            grid[ny][nx] += 1  # 周圍的人驚恐值加 1
    # 執行完畢,要印出答案,不能印出最右側、最下方的哨兵,-1 要換成 x
    for row in grid[:n]:
        print("".join([str(i) if i != -1 else "x" for i in row[:n]]))


2025年10月2日 星期四

ZeroJudge 解題筆記:f164. 萬球同心移位之章

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


ZeroJudge 題目連結:f164. 萬球同心移位之章

解題想法


這題絕對不要真的用鏈結串列解題,因為要找到鏈結串列中指定的值只能從頭開始依序往下找,一定會超時。用兩個陣列儲存每一個節點的左、右節點編號,移動節點時只要修改對應的節點編號即可。

Python 程式碼


最後一筆測資記憶體爆掉。
n, m, q = map(int, input().split())  # n 顆球,m 次操作,q 次查詢
pre = [(i-1+n)%n for i in range(n)]  # 每顆球的前一顆球
nxt = [(i+1)%n for i in range(n)]  # 每顆球的後一顆球
for _ in range(m):  # 執行 m 次
    d, a, b = input().split()  # 方向 d,a 球移到 b 球旁邊
    if a == b: continue  # 如果 a 等於 b,不移動
    a = int(a); b = int(b)  # 轉成整數
    nxt[pre[a]] = nxt[a]  # a 原來左側的球接到 a 原來右側的球
    pre[nxt[a]] = pre[a]  # a 原來右側的球接到 a 原來左側的球
    if d == 'R':  # 逆向
        le = pre[b]  # 暫存 b 原來左側的球
        nxt[le] = a  # b 原來左側的球接到 a
        pre[b] = a  # b 的左側接到 a
        pre[a] = le  # a 左側接到 le
        nxt[a] = b  # a 右側接到 b
    else:  # 順向
        ri = nxt[b]  # 暫存 b 原來右側的球
        pre[ri] = a  # b 原來右側的球接到 a
        nxt[b] = a  # b 的右側接到 a
        pre[a] = b  # a 的左側接到 b
        nxt[a] = ri  # a 的右側接到 ri
arr = tuple(map(int, input().split()))
for a in arr[:-1]: print(pre[a], nxt[a], end=" ")
print(pre[arr[-1]], nxt[arr[-1]])


2025年10月1日 星期三

ZeroJudge 解題筆記:e984. 連假時在做什麼?有沒有空?可以來打code嗎?

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


ZeroJudge 題目連結:e984. 連假時在做什麼?有沒有空?可以來打code嗎?

解題想法


用一個自訂函式 find_lln 找第 k 項的 LunlunNumber。在函式中用一個 deque 儲存待處理的數字,先放入 1 ~ 9,再用一個 while 迴圈,當 que 還有資料繼續執行;在迴圈中每次取出 que 開頭的數字存入 num,計數器 cnt 數量加 1,如果 cnt 等於 k,已經找到答案,回傳 num;如果 cnt 小於 k,取出 num 的個位數 last_digit,計算 last_digit 加減 1、不變、加 1 的數值 next_digit,如果 next_digit 在 1 到 9 之中,將新的數值加入 que 之中。

Python 程式碼


單筆測資,使用時間約為 2 s,記憶體約為 93.2 MB,通過測試。
from collections import deque

def find_lln(k):  # 找第 k 位的 Lunlun Number
    que = deque([i for i in range(1, 10)])  # 待處理的數字,先放入 1 ~ 9
    cnt = 0  # 計數器
    while que:  # 當 que 還有資料繼續執行
        num = que.popleft()  # 取出 que 開頭的數字
        cnt += 1  # 計數器加 1
        if cnt == k:  # 如果是第 k 位
            return num  # 回傳 num 並離開函式
        last_digit = num%10  # 取出個位數
        for delta in (-1, 0, 1):  # 個位數的差值 -1, 0, 1
            next_digit = last_digit + delta  # 下一個個位數值
            if 0 <= next_digit <= 9:  # 如果在 0 ~ 9 之間
                que.append(num*10 + next_digit)  # 新的數值加入 que
    return 0  # 預設的回傳值,理論上不會用到

print(find_lln(int(input())))


2025年9月30日 星期二

ZeroJudge 解題筆記:e698. OREOREO!

作者:王一哲
日期:2025年9月30日


ZeroJudge 題目連結:e698. OREOREO!

解題想法


我先計算 O 的部分較寬及 RE 的部分較寬兩種狀況下,分別要印出的 O 及 RE 的字串。接下來讀取 n 塊餅乾的組成方式,依序輸出每一塊餅乾對應的形狀。

Python 程式碼


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

for line in sys.stdin:
    w1, h1 = map(int, line.split())
    w2, h2 = map(int, sys.stdin.readline().split())
    c1, c2 = sys.stdin.readline().split()
    if w1 > w2:  # O 的部分較寬
        O = c1*w1
        RE = " "*((w1-w2)//2) + c2*w2
    else:  # RE 的部分較寬
        O = " "*((w2-w1)//2) + c1*w1
        RE = c2*w2
    n = int(sys.stdin.readline())  # 接下來有 n 塊餅乾
    for _ in range(n):  # 執行 n 次
        cookie = sys.stdin.readline().strip()  # 餅乾的組成
        i = 0  # 從 cookie 讀取資料用的索引值
        while i < len(cookie):  # 如果 i 還沒有出界時繼續執行
            if cookie[i] == "O":  # 如果是 O
                for _ in range(h1): print(O)  # 印出 h1 行的 O
                i += 1  # i 加 1
            elif cookie[i] == "R":  # 如果是 RE
                for _ in range(h2): print(RE)  # 印出 h2 行的 RE
                i += 2  # i 加 2
        print()  # 跑完一塊餅乾要換行


2025年9月29日 星期一

ZeroJudge 解題筆記:e623. 2. PPAP

作者:王一哲
日期:2025年9月29日


ZeroJudge 題目連結:e623. 2. PPAP

解題想法


先用一個 while 迴圈,計算序號 n 是第 m 輪領到東西,計算時每一輪會將 n 減去這一輪的數量。跑完 while 迴圈之後,如果 n 等於 0,代表是第 m 輪的最後一個人,印出 Pineapple pen; 反之進到下一輪,先將 m 加 1,計算 n 對 m 取整數除法的結果,輸出對應的物品名稱。

Python 程式碼


使用時間約為 46 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # 編號
m = 0  # 第 m 輪
s = 0  # 第 m 輪的數量,每次加 4
while n >= s+4:  # 如果 n 的數量大於等於 s+4,還有下一輸,繼續執行
    m += 1; s += 4  # m 加 1;s 加 4
    n -= s  # n 減去 s

if n == 0:  # 剛好是第 m 輪的最後一個人
    print("Pineapple pen")  # 印出 Pineapple pen
else:  # 要再到下一輪
    m += 1  # m 加 1
    if n%m == 0: n -= 1
    item = n // m
    if item == 0: print("Pen")
    elif item == 1: print("Pineapple")
    elif item == 2: print("Apple")
    else: print("Pineapple pen")


2025年9月28日 星期日

ZeroJudge 解題筆記:e622. 3. 虛擬寵物大師 (Master)

作者:王一哲
日期:2025年9月28日


ZeroJudge 題目連結:e622. 3. 虛擬寵物大師 (Master)

解題想法


我另外寫兩個函式,函式 ivcp 輸入 iv 值,回傳升級時增加的 cp 值;函式 upgrade 輸入原有的星塵沙子數量 star,iv 值、原來的 cp 值,計算升級後的 cp 值。

Python 程式碼


使用時間約為 38 ms,記憶體約為 3.4 MB,通過測試。
# 輸入 iv 值,回傳升級時增加的 cp 值
def ivcp(iv):
    if 0 <= iv <= 29: return 10
    elif 30 <= iv <=39: return 50
    elif 40 <= iv <= 45: return 100

# 輸入原有的星塵沙子數量 star,iv 值、原來的 cp 值,計算升級後的 cp 值
def upgrade(star, iv, cp):
    while star >= 1000:
        star -= 1000
        cp += ivcp(iv)
    return cp

# 解題過程
n, s = map(int, input().split())  # 寵物數量 n,原有的星塵沙子數量 s
imax, idx = 0, 0  # 升級後最高的 cp 值及寵物編號
for i in range(1, n+1):  # 讀取 n 行資料
    c, v = map(int, input().split())  # 讀取原來的 cp 值、iv 值
    re = upgrade(s, v, c)  # 呼叫 upgrade,代入 s, v, c,計算升級後的 cp 值
    if re > imax:  # 如果 re 大於 imax
        imax = re  # 更新 imax
        idx = i  # 更新 idx
print(f"{idx:d} {imax:d}")  # 印出答案


2025年9月27日 星期六

ZeroJudge 解題筆記:e621. 1. 免費停車 (Free Parking)

作者:王一哲
日期:2025年9月27日


ZeroJudge 題目連結:e621. 1. 免費停車 (Free Parking)

解題想法


這題應該是多行測資,但是題目沒有說清楚。讀取測資中的 A、B、C 三個數字之後,用 for 迴圈跑 i = A-1 到 i = B-1,當 i 不能被 C 整除就加入答案之中。

Python 程式碼


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

for line in sys.stdin:
    N = int(line)
    for _ in range(N):
        A, B, C = map(int, input().split())
        ans = []
        for i in range(A+1, B):
            if i%C != 0: ans.append(i)
        if ans: print(*ans)
        else: print("No free parking spaces.")