# Zerojudge實作詳解
**詳解連結:** [a054](https://hackmd.io/@oateacher/a054)
**詳解連結:** [a020](https://hackmd.io/@oateacher/a020)
**詳解連結:** [a065](https://hackmd.io/@oateacher/a065)
**詳解連結:** [a524](https://hackmd.io/@oateacher/a524)
**詳解連結:** [c317](https://hackmd.io/@oateacher/c317)
**詳解連結:** [c657](https://hackmd.io/@oateacher/c657)
**詳解連結:** [d097](https://hackmd.io/@oateacher/d097)
**詳解連結:** [d478](https://hackmd.io/@oateacher/d478)
**詳解連結:** [e566](https://hackmd.io/@oateacher/e566)
**詳解連結:** [a417](https://hackmd.io/@oateacher/a417)
**詳解連結:** [a468](https://hackmd.io/@oateacher/a468)
**題號:** a001
**名稱:** 哈囉
**說明:** 撰寫一個程式可以讀入指定的字串,並輸出另一個指定的字串
**測資:**

**程式碼(參考):**
```javascript
# a001 使用連續 IPO 輸出入資料練習
import sys
for s in sys.stdin:
print("hello, "+s)
```
**題號:** a002
**名稱:** 簡易加法
**說明:** 此題目需要輸入兩個數字,最後輸出兩個數字的總和
**測資:**

**程式碼(參考):**
```javascript
import sys
#start
for s in sys.stdin:
data = s.split()
number = int(data[0])+int(data[1])
print(number)
```
**題號:** a003
**名稱:** 兩光法師占卜術
**說明:**
* 題目的占卜術能夠輸入一個日期並依照公式後換算得到三種結果 (普通、吉、大吉)
* 換算的公式如下:
M=月
D=日
S=(M*2+D)%3
**測資:**

**程式碼(參考):**
```javascript
import sys
for s in sys.stdin:
nums = [ int(i) for i in s.split() ]
M = nums[0]
D = nums[1]
S = (M*2+D)%3
if S==0:
print("普通")
elif S==1:
print("吉")
else:
print("大吉")
```
**題號:** a004
**名稱:** 文文的求婚
**說明:**
* 整理題目說明可以發現此題是閏年問題,給定一個年份,請依照閏年的檢查方法判斷是否為閏年
* 提示 :
西元年被4整除且不被100整除,或被400整除者即為閏年
使用 cin , cout 來進行輸入輸出
**測資:**

**程式碼(參考):**
```javascript
while True:
try:
year = int(input())
if year%4 == 0 and year%100 !=0:
print("閏年")
elif year%400 == 0:
print("閏年")
else:
print("平年")
except:
break
```
**題號:** a005
**名稱:** Eva 的回家作業
**說明:** Eva的家庭作業裏有很多數列填空練習。填空練習的要求是:已知數列的前四項,填出第五項。因 為已經知道這些數列只可能是等差或等比數列,她決定寫一個程式來完成這些練習。
**測資:**

**程式碼(參考):**
```javascript
import sys
#start
t= int(input())
for i in range(t):
seq = list(map(int, input().split()))
isArithmetic = False
isGeometric = True
# 判斷等差
diff1 = seq[1]-seq[0]
diff2 = seq[2]-seq[1]
diff3 = seq[3]-seq[2]
if diff1 == diff2 and diff2 == diff3:
isArithmetic = True
diff = int(seq[3]/seq[2]);
# 判斷等比
for i in range(0, 3+1):
if seq[i]%diff != 0:
isGeometric = False
break
if isArithmetic == True:
diff = diff1
for i in range(4):
print(seq[i], end=' ')
print(seq[3]+diff)
else:
for i in range(4):
print(seq[i], end=' ')
print(seq[3]*diff)
```
**題號:** a009
**名稱:** 解碼器
**說明:**
* 在密碼學裡面有一種很簡單的加密方式,就是把明碼的每個字元加上某一個整數K而得到密碼的字元(明碼及密碼字元一定都在ASCII碼中可列印的範圍內)。例如若K=2,那麼apple經過加密後就變成crrng了。解密則是反過來做。這個問題是給你一個密碼字串,請你依照上述的解密方式輸出明碼。至於在本任務中K到底是多少,請自行參照Sample Input及Sample Output推出來吧!相當簡單的。
* 提示 :
cin.get(char) 可一次讀取一個字元
getline(cin, string) 可一次讀取完整的一行
中文翻譯 Lucky Cat
**測資:**

**程式碼(參考):**
```javascript
import sys
for s in sys.stdin:
data = list(s)
for i in range(len(data)):
t = ord(data[i])
print(chr(t-7), end='')
print()
```
**題號:** a024
**名稱:** 最大公因數(GCD)(註:先備知識-輾轉相除法)
**說明:**
* 給定兩個整數,請求出它們的最大公因數
* 提示 :
GCD 數學 最大公因數 迴圈
**測資:**

**程式碼(參考):**
```javascript
def GCD(a, b):
if a<b:
a, b = b, a
while True:
if(b != 0):
c= int(a%b)
a = b
b= c
else:
break
return a
#start
s = input()
data = s.split()
a = int(data[0])
b = int(data[1])
r = GCD(a, b)
print(r)
```
**題號:** C295(作業-Hard)
**名稱:** 求和
**說明:**
* 給定N群數字,每群都恰有M個正整數。若從每群數字中各選擇一個數字 (假設第 i群所選出數字為ti),將所選出的N個數字加總即可得和 S = t1+t2+…+ +…+ tN。請寫程式計算 S的最大值 (最大總和 ),並判斷各群所選出的數字是否可以整除 S。
* 提示 :
(範例一說明) 挑選的數字依序是 5, 6, 1,總和S=12。而此三數中可整除S的是 6與 1,6在第二群,1在第3群所以先輸出6再輸出1。注意,1雖然也出現在第一群,但她不是第一群中挑出的數字,所以順序是先 6後 1。
(範例二說明) 挑選的數字依序是6,9,7,9,總和 S= 31 。而此四數中沒有可整除 S的, 所以第二行輸出 -1。
* 評分說明:輸入包含若干筆測試資料,每一的執行時間限制 (time limit)均為 1秒,依正確通過測資筆數給分。 其中:
第 1子題組 20 分: 1≦ N ≦ 20 ,M = 1。
第 2子題組 30 分: 1≦ N ≦ 20 ,M = 2。
第 3子題組 50 分: 1≦ N ≦ 20 ,1≦ M ≦ 20 。
**測資:**

**程式碼(參考):**
```javascript
#
# c295: 最大和
#
while True:
try:
#start
s1 = input()
s1 = list(map(int, s1.split()))
N = s1[0]
M = s1[1]
# data 為二維串列結構
data = []
for i in range(0, N):
# 每次讀取一橫排資料, 轉成 row 串列, 接著加入 data 串列
s2 = input()
row = list(map(int, s2.split()))
data.append(row)
# 使用 i, j 變數直接存取單一元素的工具, 此段可刪除
#for i in range(0, N):
# for j in range(0, M):
# print(data[i][j], end=' ')
# print()
S = 0
maxvalue = []
for i in range(0, N):
# 每組 row 之間的資料, 經排序後最後一個元素為最大值
data[i].sort()
S = S+ data[i][M-1]
maxvalue.append(data[i][M-1])
print(S)
divisor_count =0
for i in range(0, N):
if S%maxvalue[i] == 0:
divisor_count +=1
print(maxvalue[i], end=' ')
if divisor_count == 0:
print("-1")
else:
print()
except:
break
```
**題號:** c462
**名稱:** apcs 交錯字串
**說明:**
* 問題描述
一個字串如果全由大寫英文字母组成,我們稱為大寫字串;如果全由小寫字母组成則稱為小寫字串。字串的长度是它所包含字母的個數,在本题中,字串均由大小寫英文母組成假設k是一個自然數,一個字串被稱為「k-交錯字串」,如果它是由長度為k的大寫字串與長度為k的小寫字串交錯串接組成。舉例來說,「StRiNg」是一個1-交錯字,因為它一個大寫一個小寫交替出現;而「heLLow」是一個2-交錯字串,因為它是兩個小寫接兩個大寫再接兩個小寫。但不管k是多少,「aBBaaa」、「BaBaBB」、「aaaAAbbCCCC」都不是k-交錯字串。本題的目標是對於給定k值,在一個輸入字串找出最長一段連續子字串滿足k-交錯字串的要求。例如k=2且輸入「aBBaaa」,最長的k-交錯字串是「BBaa」,長度為4。又如k=1且輸入「BaBaBB」,最長的k-交錯字串是「BaBaB」,長度為5。
請注意,滿足條件的子字串可能只包含一段小寫或大寫字母而無交替,如範例二。此外,也可能不存在滿足條件的子字串,如範例四。
* 提示 :
輸入包含若干筆測試資料,每一筆測試資料的執行時間限制(time limit)均為1秒,依正確通過測資筆數給分。
其中:
第1子題組20分,字串長度不超過20且k=1。
第2子題組30分,字串長度不超過100且k ≤ 2。
第3子題組50分,字串長度不超過100,000且無其他限制。
**測資:**

**程式碼(參考):**
```javascript
#
# c462 交錯字串
#
while True:
try:
#start
K = int(input())
string = input()
upper = 0 #紀錄字串中,大寫數量
lower = 0 #紀錄字串中,小寫數量
lenTemp = 0 #目前找到的K-string長度
maxLen = 0 #最長的K-string
prevChar = '' #upper/lower
if string[0].isupper() == True:
prevChar = 'u'
upper = 1
if K == 1:
lenTemp = K
maxLen = lenTemp
else:
prevChar = 'l'
lower = 1
if K == 1:
lenTemp = K
maxLen = lenTemp
for i in range(1, len(string)):
# 大 -> 大
#累加(if K>1)
if string[i].isupper() and prevChar == 'u':
upper += 1
lower = 0
if upper == K:
lenTemp += K
maxLen = max(lenTemp, maxLen)
if upper > K:
#EX AAA,2string==>lenTemp=2
#EX aaAAA,2string==>lenTemp=2
lenTemp = K
# 小 -> 小
#累加(if K>1)
elif string[i].islower() and prevChar == 'l':
upper = 0
lower +=1
if lower == K:
lenTemp += K
maxLen = max(lenTemp, maxLen)
if lower > K:
lenTemp = K
# 小 -> 大
elif prevChar == 'l' and string[i].isupper():
if lower < K:
lenTemp = 0
upper = 1
lower = 0
if K == 1:
lenTemp += K
maxLen = max(lenTemp, maxLen)
prevChar = 'u'
# 大 -> 小
elif prevChar == 'u' and string[i].islower():
if upper < K:
## AAAaa 2string
lenTemp = 0
upper = 0
lower = 1
if K == 1:
lenTemp += K
maxLen = max(lenTemp, maxLen)
prevChar = 'l'
print(maxLen)
except:
break
```
**題號:** c636
**名稱:** 12生肖
**說明:**
* 民國元年 ( 1912 ) 是鼠年。
給定若干個民國年份 -100 ~ 107
請輸出該年生肖為何。
* 提示 :
array number 餘數
**測資:**

**程式碼(參考):**
```javascript
import sys
sign = ["鼠", "牛", "虎", "兔", "龍",
"蛇", "馬", "羊", "猴", "雞",
"狗", "豬"]
#start
for s in sys.stdin:
year = int(s)
if year>0:
if year%12==0:
print(sign[11])
else:
index = year%12-1
print(sign[index])
elif year<0:
abs_year = abs(year)
if abs_year%12==0:
print(sign[0])
else:
index = 12-abs_year%12
print(sign[index])
```
**題號:** e447
**名稱:** queue 練習
**說明:**
* 請你實作queue相關的幾個基本操作:
在隊伍尾端加入元素。
輸出隊伍最前端的元素。
刪除隊伍最前端的元素。
* 提示 :
**測資:**

**程式碼(參考):**
```javascript
queue = []
MAX_SIZE = 100
def enqueue(data):
queue.append(data)
def dequeue():
data = queue.pop(0)
return data
def isFull():
if len(queue) == MAX_SIZE:
return True
else:
return False
def isEmpty():
if len(queue) == 0:
return True
else:
return False
def front():
return queue[0]
def rear():
return queue[len(queue)-1]
#start
N = int(input())
for i in range(N):
s = input()
data = [ int(x) for x in s.split() ]
if data[0] == 1:
enqueue(data[1])
elif data[0] == 2:
if isEmpty() == True:
print(-1)
else:
print(front())
elif data[0] == 3:
if isEmpty() == False:
dequeue()
```
**題號:** f312
**名稱:** 人力分配
**說明:**

**測資:**
**程式碼(參考):**
```javascript
#
# f312 人力分配
#
#start
a1, b1, c1 = map(int, input().split())
a2, b2, c2 = map(int, input().split())
n = int(input())
max_benfit = -1000000
for x in range(0, n+1):
x1 = x
x2 = n-x1
y1 = a1*x1*x1+b1*x1+c1
y2 = a2*x2*x2+b2*x2+c2
Y = y1+y2
#print(x1, x2, Y)
if Y > max_benfit:
max_benfit = Y
print(max_benfit)
```
**題號:** f313
**名稱:** 人口遷移
**說明:**

**測資:**
**程式碼(參考):**
```javascript
#
# f313 人口遷移
#
def show_population(arr, R, C):
for i in range(R):
for j in range(C):
print(arr[i][j], end=' ')
print()
# ( 0,-1)
# (-1, 0)( 0, 0)( 1, 0)
# ( 0, 1)
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
#start
R, C, k, m = map(int, input().split())
population = []
move_per_day = [ [ 0 for i in range(C)] for j in range(R) ]
for i in range(R):
row = list(map(int, input().split()))
population.append(row)
idx = 1
while idx <= m:
# 遷出人口
for i in range(R):
for j in range(C):
now_move = population[i][j]//k
#print("%d, %d, now move=%d" % (i, j, now_move))
direction = 0
if now_move > 0:
for c in range(4):
now_c = j+dx[c]
now_r = i+dy[c]
#print(now_r, now_c)
if (0 <= now_c < C) and (0 <= now_r < R):
#print(now_r, now_c, population[now_r][now_c])
if population[now_r][now_c] != -1:
direction += 1
move_per_day[now_r][now_c] += now_move
population[i][j] -= now_move*direction
#show_population(move_per_day, R, C)
# 遷入移動人口
for i in range(R):
for j in range(C):
population[i][j] += move_per_day[i][j]
#reset 移動量
move_per_day = [ [ 0 for i in range(C)] for j in range(R) ]
#show_population(population, R, C)
idx += 1
#show_population(population, R, C)
max_p = 0
min_p = 100
for i in range(R):
for j in range(C):
if population[i][j] != -1:
max_p = max(max_p, population[i][j])
min_p = min(min_p, population[i][j])
print(min_p)
print(max_p)
```
**題號:** f579
**名稱:** 購買力
**說明:**
* 給兩個整數a、b 代表你要觀察的商品編號。商場在每一位客人的購物車都放置了一個感應器,能夠得知每位客人將商品放入購物車或拿出購物車。感應器存放的紀錄是一連串的整數,一個正整數x表示這位客人將一個編號是x的商品放入他的購物車,一個負數-x表示這位客人將一個編號是x的商品從他的購物車移除。現在有n 位客人的購物車紀錄,你想要統計有幾位客人最後有購買商品a與商品b,一個客人有購買商品x表示商品x在他的購物車中放入的次數比拿出還多。
* 提示 :
**測資:**

**程式碼(參考):**
```javascript
#
# f579 購買力
#
a, b = map(int, input().split())
n = int(input())
num = 0
for i in range(n):
record = list(map(int, input().split()))
buy_A = 0
buy_B = 0
for x in range(len(record)):
if record[x] > 0:
if record[x] == a:
buy_A += 1
if record[x] == b:
buy_B += 1
elif record[x] < 0:
if abs(record[x]) == a:
buy_A -= 1
if abs(record[x]) == b:
buy_B -= 1
if buy_A>0 and buy_B>0:
num += 1
print(num)
```
**題號:** g275
**名稱:** 七言對聯
**說明:**
* 中文依照發音方式可以分為平聲與仄聲,假設我們把平聲標記為1、而仄聲標記為0、一個七言對聯包含兩個句子,每個句子包含恰好七個字。
* 七言對聯有三個限制:
A: 二四不同二六同:每一句第二、四個字必須不同平仄,而第二、六個字必須相同平仄
B: 仄起平收:第一句的結尾必須為仄聲,第二句的結尾必須為平聲
C: 上下相對:第一、二句的第二、四、六個字平仄必須不同
* 給你n 組對聯,分別用0,1代表平仄,請輸出它違反了哪幾條規則
若以上規則皆無違反,請輸出None
* 提示 :
**測資:**

)
**程式碼(參考):**
```javascript
#
# g275: 七言對聯
#
# 0: 平聲
# 1: 仄聲
#start
n = int(input())
for i in range(n):
p1 = list(map(int, input().split()))
p2 = list(map(int, input().split()))
violation = 0
#A
if p1[1] != p1[3] and p2[1] != p2[3]:
if p1[1] == p1[5] and p2[1] == p2[5]:
pass
else:
violation += 1
print("A", end='')
else:
violation += 1
print("A", end='')
#B
if p1[6] == 1 and p2[6] == 0:
pass
else:
violation += 1
print("B", end='')
#C
if (p1[1]+p2[1]) == 1 and (p1[3]+p2[3]) == 1 and (p1[5]+p2[5]) == 1:
pass
else:
violation += 1
print("C", end='')
if violation >0:
print()
else:
print("None")
```
**題號:** h081
**名稱:** 程式交易
**說明:**

**測資:**

**提示:**

**程式碼(參考):**
```javascript
#
# h081: 程式交易
#
#start
n, D = map(int, input().split())
prices = list(map(int, input().split()))
x=0
haveStock = False
benfit = 0
for i in range(n):
#print(x, prices[i], benfit)
if x==0 or (prices[i] <= (x-D) and haveStock == False):
x = prices[i]
haveStock = True
if prices[i] >= (x+D) and haveStock == True:
benfit += prices[i]-x
x = prices[i]
haveStock = False
print(benfit)
```
**題號:** i213
**名稱:** stack 練習
**說明:**
* 請你實作stack相關的幾個基本操作:
在堆疊頂端加入元素。
輸出堆疊最頂端的元素。
刪除堆疊最頂端的元素。
* 提示 :
**測資:**

**程式碼(參考):**
```javascript
#
# i213: stack 練習
#
stack = []
def push(data):
stack.append(data)
def pop():
r = stack.pop()
return r
def top():
now_size = len(stack)
t = stack[now_size-1]
return t
def size():
print(len(stack))
def empty():
if len(stack) == 0:
return True
else:
return False
#start
N = int(input())
for i in range(N):
row = list(map(int, input().split()))
if len(row) == 1:
k = row[0]
else:
k = row[0]
d = row[1]
if k == 1:
push(d)
elif k == 2:
if empty() == True:
print(-1)
else:
print(top())
elif k == 3:
if empty() == False:
pop()
```
**題號:** i400
**名稱:** 字串解碼
**說明:**

**測資:**

* 提示 :
範例測資一,如題目所述
範例測資二過程如下
e = 111110,
出現的數量為奇數次,因此需要將字串 "QWERTY" 切半翻轉成 "RTYQWE",經過 01 字串的轉換後會得到 "EWQYTR"。
e = 101101,
出現的數量為偶數次,因此不用翻轉字串,經過 01 字串的轉換後會得到 "RETYWQ"。
e = 000000,
出現的數量為偶數自,因此不用翻轉字串,經過 01 字串的轉換後會得到 "RETYWQ"。
**程式碼(參考):**
```javascript
#
# i400: 字串解碼
#
def step2(T, ei, n):
tString = ""
T = list(T)
for dx in range(n-1, -1, -1):
if ei[dx] == '0':
tString = T[len(T)-1] + tString
#print("R, ", end=' ')
else:
tString = tString + T[len(T)-1]
#print("F, ", end=' ')
T.pop()
#print(T, tString)
return tString
def step1(T, ei, n):
checkE = 0
for i in ei:
if i == '1':
checkE += 1
if checkE%2 == 0:
return T
else:
if n%2 == 0:
subT1 = T[0:n//2]
subT2 = T[n//2:n]
#print(subT2, subT1)
return subT2+subT1
else:
subT1 = T[0:n//2]
mid = T[n//2]
subT2 = T[n//2+1:n]
#print(subT2, mid, subT1)
return subT2+mid+subT1
#start
m, n = map(int, input().split())
e = []
for i in range(m):
encode = list(input())
e.append(encode)
T = input()
S = ""
temp = T
for i in range(m-1, -1, -1):
temp = step2(temp, e[i], n)
#print(temp)
temp = step1(temp, e[i], n)
#print(temp)
print(temp)
```
# **回家作業挑戰題詳解**
**題號:** 9-5挑戰題
**名稱:** 解碼器(參考Zerohudge-a009)
**說明:**

**程式碼(參考):**
```javascript
import sys
#start
for s in sys.stdin:
data = s.split()
code = data[0]
K = int(data[1])
decode = ""
for i in range(len(code)):
value = ord(code[i]) + K
decode += chr(value)
print(decode)
```