# 0-7 陣列及0-8 迴圈
講義不是我寫的,網址在此 https://emanlaicepsa.github.io/2020/10/21/0-index/
我只是將自己寫的練習題程式碼記錄下來。
最後更新日期:2024年10月6日
## [TOJ: 104 / 星星樹](https://toj.tfcis.org/oj/pro/104/)
### Python 程式碼
執行時間最久約為 27 ms,使用記憶體最多約為 4164 kB,通過測試。
```python=
n = int(input())
for i in range(n):
for j in range(1, (n-i-1)+2*(i+1)):
print(" " if j<n-i else "*", end="")
print()
```
### C++ 程式碼
執行時間最久約為 2 ms,使用記憶體最多約為 308 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(0),cin.tie(0);
int n; cin >> n;
for(int i=0; i<n; i++) {
for(int j=1; j<(n-i-1)+2*(i+1); j++) {
if (j<n-i) cout << " ";
else cout << "*";
}
cout << "\n";
}
return 0;
}
```
## [TOJ: 106 / 精靈的家在哪](https://toj.tfcis.org/oj/pro/106/)
### Python 程式碼
執行時間最久約為 20 ms,使用記憶體最多約為 4116 kB,通過測試。
```python=
n = 2
while n%71: n = n*2 + 1
if n%3 == 0: print("right")
else: print("left")
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 284 kB,通過測試。
```cpp=
#include<iostream>
using namespace std;
int main() {
int n = 2;
while(n%71) n = n*2 + 1;
if (n%3 == 0) cout << "right\n";
else cout << "left\n";
return 0;
}
```
## [TOJ: 107 / 紀念品的難題](https://toj.tfcis.org/oj/pro/107/)
### Python 程式碼
執行時間最久約為 21 ms,使用記憶體最多約為 4116 kB,通過測試。
```python=
n, tot = 30, 0
for i in range(n):
tot += 1
for j in range(i+1):
tot += 1
for k in range(j+1):
tot += j+k+1
print(tot)
```
比較好的寫法,執行時間最久約為 23 ms,使用記憶體最多約為 3960 kB,通過測試。
```python=
n, tot = 30, 0
for i in range(1, n+1):
son = 1
gdau = i
ggson = i * (i*(i+1)//2)
tot += son + gdau + ggson
print(tot)
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 284 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
int n = 30, tot = 0;
for(int i=0; i<n; i++) {
tot++;
for(int j=0; j<i+1; j++) {
tot++;
for(int k=0; k<j+1; k++) {
tot += j+k+1;
}
}
}
cout << tot << "\n";
return 0;
}
```
比較好的寫法,執行時間最久約為 1 ms,使用記憶體最多約為 128 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
int n = 30, tot = 0;
for(int i=1; i<=n; i++) {
int son = 1;
int gdau = i;
int ggson = i * (i*(i+1)/2);
tot += son + gdau + ggson;
}
cout << tot << "\n";
return 0;
}
```
## [TOJ: 110 / 六芒星的咒符](https://toj.tfcis.org/oj/pro/110/)
### Python 程式碼
寫法1,先産生上半部三角形資料,複製、反轉成下半部三角形資料,最後再合併成六芒星。執行時間最久約為 30 ms,使用記憶體最多約為 4332 kB,通過測試。
```python=
n = int(input()) # 三角形個數
for _ in range(n): # 執行 n 次
h = int(input()) # 三角形高度
w = 2*h - 1 # 三角形底部寬度
up = [] # 上半部三角形每列的形狀
for i in range(h): # 執行 h 次
s = " "*((w-1)//2-i) # 左側的空格
s += "*"*(2*i+1) # 中間的 *
up.append(s) # 將組合而成的字串加入 up
down = up.copy() # 複製 up 的資料到 down
down.reverse() # 將 down 的資料反過來
tri = up[:h-3] + [down[0]] + up[h-2:] + down[3:] # 合併 up 及 down 成為六芒星
for t in tri: print(t) # 依序印出 tri 的資料
```
寫法2,只産生上半部三角形資料,用 for 迴圈控制要印出的資料範圍及順序。執行時間最久約為 23 ms,使用記憶體最多約為 4160 kB,通過測試。
```python=
n = int(input()) # 三角形個數
for _ in range(n): # 執行 n 次
h = int(input()) # 三角形高度
w = 2*h - 1 # 三角形底部寬度
tri = [] # 上半部三角形每列的形狀
for i in range(h): # 執行 h 次
s = " "*((w-1)//2-i) # 左側的空格
s += "*"*(2*i+1) # 中間的 *
tri.append(s) # 將組合而成的字串加入 tri
for i in range(h-3): print(tri[i]) # 印出 tri[0] ~ tri[h-2]
print(tri[-1]) # 印出 tri[-1],也可以寫成 tri[h-1]
for i in range(h-2, h): print(tri[i]) # 印出 tri[h-2] ~ tri[h-1]
for i in range(h-4, -1, -1): print(tri[i]) # 印出 tri[h-4] ~ tri[0]
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 284 kB,通過測試。
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main() {
int n; cin >> n; // 三角形個數
for(int i=0; i<n; i++) { // 執行 n 次
int h; cin >> h; // 三角形高度
int w = 2*h - 1; // 三角形底部寬度
string tri[h]; // 上半部三角形每列的形狀
for(int j=0; j<h; j++) { // 執行 h 次
string s = ""; // 空字串
for(int k=0; k<(w-1)/2-j; k++) s += " "; // 左側的空格
for(int k=0; k<2*j+1; k++) s += "*"; // 中間的 *
tri[j] = s; // 將組合而成的字串加入 tri
}
for(int j=0; j<h-3; j++) cout << tri[j] << "\n"; // 印出 tri[0] ~ tri[h-2]
cout << tri[h-1] << "\n"; // 印出 tri[h-1]
for(int j=h-2; j<h; j++) cout << tri[j] << "\n"; // 印出 tri[h-2] ~ tri[h-1]
for(int j=h-4; j>=0; j--) cout << tri[j] << "\n"; // 印出 tri[h-4] ~ tri[0]
}
return 0;
}
```
## [TOJ: 114 / 我閉著眼](https://toj.tfcis.org/oj/pro/114/)
### Python 程式碼
執行時間最久約為 30 ms,使用記憶體最多約為 4108 kB,通過測試。
```python=
grid = [list(map(int, input().split())) for _ in range(5)] # 讀取盤面
flag = False # 是否有找到解
for r in range(5): # 依序檢查第 0 ~ 4 列
if flag: break # 如果已找到解,中止迴圈
for c in range(4): # 依序檢查第 0 ~ 3 欄
now = grid[r][c] # 現在的格子數字
if now == grid[r][c+1] and now == grid[r][c+2]: # 檢查右側兩欄
flag = True; break # 如果數字皆等於 now,找到解,中止迴圈
for c in range(6): # 依序檢查第 0 ~ 5 欄
if flag: break # 如果已找到解,中止迴圈
for r in range(3): # 依序檢查第 0 ~ 2 列
now = grid[r][c] # 現在的格子數字
if now == grid[r+1][c] and now == grid[r+2][c]: # 檢查下方兩列
flag = True; break # 如果數字皆等於 now,找到解,中止迴圈
print("Yes" if flag else "No") # 如果找到解印出 Yes,否則印出 No
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 248 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int grid[5][6]; // 盤面資料
for(int r=0; r<5; r++)
for(int c=0; c<6; c++)
cin >> grid[r][c];
bool flag = false; // 是否有找到解
for(int r=0; r<5; r++) { // 依序檢查第 0 ~ 4 列
if (flag) break; // 如果已找到解,中止迴圈
for(int c=0; c<4; c++) { // 依序檢查第 0 ~ 3 欄
int now = grid[r][c]; // 現在的格子數字
if (now == grid[r][c+1] && now == grid[r][c+2]) { // 檢查右側兩欄
flag = true; break; // 如果數字皆等於 now,找到解,中止迴圈
}
}
}
for(int c=0; c<6; c++) { // 依序檢查第 0 ~ 5 欄
if (flag) break; // 如果已找到解,中止迴圈
for(int r=0; r<2; r++) { // 依序檢查第 0 ~ 2 列
int now = grid[r][c]; // 現在的格子數字
if (now == grid[r+1][c] && now == grid[r+2][c]) { // 檢查下方兩列
flag = true; break; // 如果數字皆等於 now,找到解,中止迴圈
}
}
}
cout << (flag ? "Yes" : "No") << "\n"; // 如果找到解印出 Yes,否則印出 No
return 0;
}
```
## [TOJ: 117 / 成績竄改](https://toj.tfcis.org/oj/pro/117/)
### Python 程式碼
執行時間最久約為 22 ms,使用記憶體最多約為 4124 kB,通過測試。
```python=
a = int(input())
imax = 0
for _ in range(a):
b = int(input())
if b > imax: imax = b
print(imax)
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 304 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int a, b, imax = 0; cin >> a;
for(int i=0; i<a; i++) {
cin >> b;
if (b > imax) imax = b;
}
cout << imax << "\n";
return 0;
}
```
## [TOJ: 119 / B. Brainwash](https://toj.tfcis.org/oj/pro/119/)
### Python 程式碼
執行時間最久約為 99 ms,使用記憶體最多約為 16052 kB,通過測試。
```python=
n = int(input())
data = [0] + list(map(int, input().split()))
t = int(input())
flag = True
for _ in range(t):
a, b = map(int, input().split())
if abs(a-b) > 8:
print("I QUIT!")
print(*data[1:])
flag = False; break
else:
data[a], data[b] = data[b], data[a]
if flag:
print("SORTED!")
print(*data[1:])
```
### C++ 程式碼
執行時間最久約為 14 ms,使用記憶體最多約為 1300 kB,通過測試。
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
int data[n+1] = {0};
for(int i=1; i<=n; i++) cin >> data[i];
int t; cin >> t;
bool flag = true;
for(int i=0; i<t; i++) {
int a, b; cin >> a >> b;
if (!flag) continue;
if (abs(a-b) > 8) {
cout << "I QUIT!\n";
for(int j=1; j<=n; j++) cout << data[j] << " \n"[j == n];
flag = false;
} else {
int c = data[a];
data[a] = data[b];
data[b] = c;
}
}
if (flag) {
cout << "SORTED!\n";
for(int j=1; j<=n; j++) cout << data[j] << " \n"[j == n];
}
return 0;
}
```
## [TOJ: 3 / GCD](https://toj.tfcis.org/oj/pro/3/)
### Python 程式碼
寫法1,輾轉相除法,執行時間最久約為 23 ms,使用記憶體最多約為 3992 kB,通過測試。
```python=
n = int(input())
for _ in range(n):
a, b = map(int, input().split())
while b: a, b = b, a%b
print(a)
```
寫法2,使用 math.gcd,執行時間最久約為 19 ms,使用記憶體最多約為 3996 kB,通過測試。
```python=
from math import gcd
n = int(input())
for _ in range(n):
a, b = map(int, input().split())
print(gcd(a, b))
```
### C++ 程式碼
寫法1,輾轉相除法,執行時間最久約為 2 ms,使用記憶體最多約為 248 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
for(int i=0; i<n; i++) {
int a, b, r; cin >> a >> b;
while(b) {
r = a%b;
a = b;
b = r;
}
cout << a << "\n";
}
return 0;
}
```
寫法2,使用 algorithm 函式庫的 gcd,執行時間最久約為 1 ms,使用記憶體最多約為 284 kB,通過測試。
```cpp=
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
for(int i=0; i<n; i++) {
int a, b; cin >> a >> b;
cout << __gcd(a, b) << "\n";
}
return 0;
}
```
## [TOJ: 8 / Scytale](https://toj.tfcis.org/oj/pro/8/)
### Python 程式碼
第3筆測資遇到 RuntimeError。
```python=
import sys
for line in sys.stdin:
n = int(line.strip()) # 角柱數量 n
s = input() # 讀取一行字串
m = len(s)//n # 字串分成 n 等份,每一份長度為 m
for i in range(n): # 依序讀取 n 個角柱
for j in range(m): # 依序讀取每個每一份第 j 個字元
print(s[j*n+i], end="") # 索引值為 j*n+i
print() # 換行
```
### C++ 程式碼
執行時間最久約為 1 ms,使用記憶體最多約為 304 kB,通過測試。
```cpp=
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; // 角柱數量 n
while(cin >> n) {
cin.ignore(); // 清除緩衝區內容,沒加這行底下的 getline 讀不到東西
string s; // 字串 s
getline(cin, s); // 讀取一行字串
int m = (int)s.size()/n; // 字串分成 n 等份,每一份長度為 m
for(int i=0; i<n; i++) // 依序讀取 n 個角柱
for(int j=0; j<m; j++) // 依序讀取每個每一份第 j 個字元
cout << s[j*n+i]; // 索引值為 j*n+i
cout << "\n"; // 換行
}
return 0;
}
```
## [TOJ: 120 / C. Counting Stars](https://toj.tfcis.org/oj/pro/120/)
### Python 程式碼
第2筆測資超時。
```python=
N = int(input())
ns = [0] + list(map(int, input().split()))
psum = [0]*(N+1)
for i in range(1, N+1): psum[i] = psum[i-1] + ns[i]
Q = int(input())
for _ in range(Q):
le, ri = map(int, input().split())
if le > ri: le, ri = ri, le # 如果 le > ri,兩者交換
print(psum[ri] - psum[le-1])
```
### C++ 程式碼
儲存加總的陣列格式要用 long long,用 int 會溢位。執行時間最久約為 73 ms,使用記憶體最多約為 3172 kB,通過測試。
```cpp=
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int N; cin >> N;
LL psum[N+1] = {0};
for(int i=1; i<=N; i++) {
int n; cin >> n;
psum[i] = psum[i-1] + n;
}
int Q; cin >> Q;
for(int i=0; i<Q; i++) {
int le, ri; cin >> le >> ri;
if (le > ri) swap(le, ri); // 如果 le > ri,兩者交換
cout << psum[ri] - psum[le-1] << "\n";
}
return 0;
}
```
## [TOJ: 485 / 重組回文](https://toj.tfcis.org/oj/pro/485/)
### Python 程式碼
第3、4筆測資超時。
```python=
n = int(input()) # 字串長度
s = input() # 字串
ans = n-1 # 答案預設為 n-1
for i in range(n-1, -1, -1): # 依序産生 n-1 ~ 0
flag = True # 是否為迴文,預設為 True
le, ri = i, n-1 # 左側索引值 le,右側索引值 ri
while le < ri: # 如果 le < ri,還沒有重疊,繼續執行
if s[le] != s[ri]: # 如果字元不同
flag = False # 已經不是迴文
break # 中止迴圈
le += 1; ri -= 1 # le 向右1格,ri 向左1格
# end of while loop
if flag: ans = i # 如果是回文,ans 為 i,答案只會越來越小
# end of for loop
print(ans) # 印出答案
```
### C++ 程式碼
執行時間最久約為 47 ms,使用記憶體最多約為 560 kB,通過測試。
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
string s; cin >> s;
int ans = n-1;
for(int i=n-1; i>=0; i--) {
bool flag = true;
for(int le=i, ri=n-1; le<ri; le++, ri--) {
if (s[le] != s[ri]) {
flag = false;
break;
}
}
if (flag) ans = i;
}
cout << ans << "\n";
return 0;
}
```
## [TOJ: 501 / pD. 團ㄎㄧㄤ遊戲](https://toj.tfcis.org/oj/pro/501/)
### Python 程式碼
原來講義上的寫法,我自己想到的寫法沒這麼精簡。比較需要解釋的是以下3行
1. 第3行:為了使索引值對到人的編號,開頭放入 0。頂多是從第n個繞回來到第n-1個,t要存2次。
2. 第6行:如果 now+1 較小,代表第i個人記憶力足夠,可以繼續接下去;如果 m[i] 較小,代表第i個人記憶力不夠,相當於以他前 m[i]-1 個人為開頭才能使他記住,因此 now 改為 m[i]。
3. 第7行:每次都要更新 ans,取 ans 及 now 較大者。
執行時間最久約為 349 ms,使用記憶體最多約為 14420 kB,通過測試。
```python=
n = int(input()) # 人數
t = list(map(int, input().split())) # 暫存每個人的記憶力
m = [0] + t + t # 每個人的記憶力
ans, now = 0, 0 # 答案 ans、目前需要的記憶力 now,皆預設為0
for i in range(1, 2*n+1): # 依序檢查第1個人 ~ 第2輪第n個人
now = min(now+1, m[i]) # 目前需要的記憶力,取 now+1 及 m[i] 較小者
ans = max(ans, now) # 答案取 ans 及 now 較大者
# end of for loop
print(min(ans, n)) # 印出 ans 及 n 較小者,每個人都能輪到是最大的答案 n
```
### C++ 程式碼
執行時間最久約為 10 ms,使用記憶體最多約為 1172 kB,通過測試。
```cpp=
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
int m[2*n+1] = {0};
for(int i=1; i<=n; i++) {
cin >> m[i]; m[i+n] = m[i];
}
int ans = 0, now = 0;
for(int i=1; i<=2*n; i++) {
now = min(now+1, m[i]);
ans = max(ans, now);
}
cout << min(ans, n) << "\n";
return 0;
}
```
------
###### tags:`演算法`、`APCS`、`Python`、`C++`