(slide ver)
You should read this slide along w/ this docs:
講師介紹
我不是專業的競程玩家,我沒有特別練習。
目前戰績 (按照時間排序):
程式競賽介紹
需要學習的技術
請乖乖使用C++,不需要太高深的語法技巧
(甚至有些競賽跟你說只有部分題能用Python解)
(CPE前三題那種隨便,都是水題)
高速寫程式碼,同時要兼顧可維護性。
題目敘述都是英文
基礎: 一些資料結構得會的,尤其是樹。
Greedy: Activity Selection、Interval Cover、Optimal Matching、Huffman Coding、scheduling…
DP:
背包: 01背包、完全背包、分組背包、各種背包
subsets(bitmask)、LCS/LIS…
圖: D/BFS、MST(也算是greedy)、Shortest-Path(Dijkstra/Bellman/Floyd/SPFA…)、Topo/DAG、強連通分量(Tarjan)、Min Cut/Max Flow、LCA…
可能是技巧?: Disjoint Set、雙指標、滑窗、rolling hash、PQ、位元枚舉、分治、cache…
沒,亂講的
看需求,如果想要打得好就要碰一點
競賽制度
ICPC:
OI (偏資奧):
不同題數: 題數高的優先 (廢話)
同題數: 看總時間,越少的優先 (也是廢話)
來看看這位玩家的分數吧
這傢伙不行啊
第1題比賽開始57分鐘後解出
第2題比賽開始20分鐘後解出
第3題比賽開始51分鐘後解出
第4題比賽開始175分鐘後解出,被罰時1次
第5題有提交2次,但沒解出來
第6題比賽開始134分鐘後解出
第7題沒有提交
57 + 20 + 51 + (175 + 20) + 134 = 457
分數: 5題,t: 457
競賽題目格式
提交作答結果
AC (Accepted)
WA (Wrong Answer)
RE (Runtime Error)
CE (Compile Error)
TLE (Time Limit Exceeded)
MLE (Memory Limit Exceeded)
程式正確
程式輸出有誤
程式跑到一半掛了
編譯錯誤
超時
記憶體用量超過限制
Online Judge
高中入門常用
中文
很多以前競賽的題目
有不少新手友善的題目
30年歷史,很多競賽題
很有名,很有名
題目量很大,幾萬題來的
屬於建中資訊社
不少有趣的校內賽題目可以打
台灣競賽/檢定資訊
分為 觀念/實作 兩部分
只想過畢業門檻的人不用看
7題
題源: onlinejudge.org
前3題,一定會有一題是從1星題題選(49題) 選出來的,把那49題都學會,你每次都可以保底1題。
程式設計競賽的最高殿堂
參賽資格難獲得
台灣最高規格的程式競賽就是ICPC亞洲區賽
賽場都有吃的,賽後有晚餐,
比賽的時候,可以去休息室拿/吃零食
每隊可以帶一個吉祥物
玩偶/棉被 應該都行
洲區賽參加資格:
NCPC (大專賽) 前40
總之歡迎各位來跟我搶我們學校的參賽資格就是
可以先看看測資,
簡單題可能看得出一些端倪,甚至是直接看出題目要幹嘛。
難一點的,可能可以看得出是圖、動態規劃。
如果看到什麼要把結果 % 1000000007的
題目可能是:
只想過畢業門檻的人不用看
如果看到什麼
題目可能是:
只想過畢業門檻的人不用看
程式部分
#include<iostream>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<map>
#include<set>
#include<vector>
#include<iterator>
#include<deque>
#include<cstring>
#include<cctype>#include
bits/
std
c++
.h
這還用說嗎?
這個檔案在 bits/ folder內
代表 standard (跟stdio/stdlib同意思)
代表 c++ (廢話)
標頭檔
#include<bits/stdc++.h>注意:
請不要在程式競賽以外的地方
像是你的專案,使用這個標頭。
標準庫內很多東西,
函數、類別、變數都存在std命名空間內
std::cout << "Hello" << std::endl;
std::vector<int> v;引入std命名空間。
因此使用時無需使用std::
#include<bits/stdc++.h>
using namespace std;
int main() {
cout << "Hello" << endl; // 不用寫 std::cout 、 std::endl
vector<int> v; // 不用寫 std::vector
}宣告陣列的小技巧
像這一題,他說有N個人,1 <= N <= 30000
所以你可能會建立一個陣列: int arr[30000] = {};
但是你要存取1 ~ 30000,所以你會減1,像是: arr[id-1]
那你不如把陣列設成: int arr[30001] = {};
可以直接用 arr[id] 存取。
題目的輸入
char c = getchar(); // 讀一個字元,EOF -> -1
c = cin.get(); // 讀一個字元,EOF -> -1
cin >> c; // 讀一個非空白字元,EOF -> 0
cin.get(c); // 讀一個非空白字元,EOF -> -1丟棄一個字元
cin.ignore();string s;
getline(cin, s);string s;
// ...
stringstream ss(s);
int i, j, k;
ss >> i >> j >> k; // read as 3 integerswhile(cin >> i) {
}string s;
while(getline(cin, s)) {
}char c;
while((c = getchar()) != EOF) {
}UVA 382,2024/12/10 CPE 題2
L1: 多個N 到0為止
int N;
// 讀 N 到 EOF or N = 0
while (cin >> N && N) {
// handle your inputs
}
UVA 11063,2025/05/20 CPE 題1
L1: 多個n (到EOF)
L2: n個數
int N;
while(cin >> N) { // 讀N到EOF
while(N--) { //讀N個b
int b;
cin >> b; // handle your inputs
}
}
UVA 10268,2024/12/10 CPE 題3
L1: 多個n (到EOF)
L2: 一行數
long long x;
while (cin >> x) {
cin.ignore();
string line;
getline(cin, line);
stringstream ss(line);
long long c;
while (ss >> c) {
// handle your inputs
}
}UVA 941,2023/10/17 CPE 題6
L1: 給T,T個Sample
L2: 一行字 + 一數
int T;
cin >> T;
int N;
string s;
while (T--) { // run T times
cin >> s >> N;
// handle your inputs
}'\n' 就是一個換行字元
endl 是一個操作符,換行 + flush buffer
flush 是 flush buffer 用的操作符
或是呼叫 cout.flush() 也行
所以,如果有需要大量換行,可以使用 '\n'
最後在 cout << flush;
或是 cout.flush();
不要一直使用 cout << endl;
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}(其實這個我也用不到)
IO優化基礎兩件套
ios::sync_with_stdio(false);取消C++與C的 I/O綁定
(預設每次C++ I/O 時,會去檢查C的I/O Buffer)
ios::sync_with_stdio(false);影響:
cin.tie(nullptr);取消cin與cout的綁定
(預設每次cin read前,都會flush一次cout)
cin.tie(&cout);cin.tie(&cout);只想過畢業門檻的人不用看
(這個屬於黑科技)
把 getchar() 改成 getchar_unlocked()
把 putchar() 改成 putchar_unlocked()
總之,這個東西沒有Thread Safety,稍快。
STL Container
Standard Template Library 內有這麼一些Container
用於存放/管理元素。
<Template> 可以存放任意型別的元素。
已經抽象過底層的資料結構,提供統一操作介面。
Iterator
每個容器皆有Iterator可以使用,
可以想像是: 指向容器元素的指標
但比指標更抽象
假設今天它是vector<int>的迭代器, 型別就是vector<int>::iterator 但我們可以用auto代替
通常,會有這四種取得迭代器的基本方法
(有些沒有,如stack / queue)
大多可以用 (+、-) (加、減) 來移動
a.begin() 指向第一個元素 *a.begin() 是第一個元素
a.begin()+1 指向第二個元素 *(a.begin()+1) 是第二個元素
但是其實我們不常使用Iterator。
我們只要先記:
*a.begin() 取第一個元素
*a.rbegin() 取最後一個元素
string
string s1 = "Hello"; // "Hello"
string s2("world"); // "world"
string s3(5, "!"); // "!!!!!"string s = "Hello"; // "Hello"
char c = s[2]; // 'l'
s[1] = "a";
cout << s; // "Hallo"s.length()
s.size()string s1 = "Hello";
string s2 = "World";
string s3 = s1 + " " + s2; // "Hello World"string s = "Hello World";
// s.substr(offset, length)
// 從s[0]取五個字元
string s2 = s.substr(0, 5); // "Hello"
// s.substr(offset)
// 從s[6]取到尾
string s3 = s.substr(6); // "World"
cout << s; // "Hello World"不改變原有的string內容
string s = "Hello World";
// s.insert(offset, str)
// 在 s[offset] 前面插入
s.insert(5, ","); // "Hello, World"
// s.erase(offset, length)
// 從 s[offset] 開始刪除 length個字元
s.erase(5, 1); // "Hello World"
// s.replace(offset, length, newString)
// 從s[offset] 開始刪除 length 個字元,換成newString
s.replace(6, 5, "World!!!!!"); // "Hello World!!!!!"
cout << s; // "Hello World!!!!!"改變原有的string內容
string s = "Hello World";
// "Hello, World"
string s2 = s.substr(0, 5) + "," + s.substr(5);
// "HelloWorld"
string s3 = s.substr(0, 5) + s.substr(5 + 1);
// "Hello World!!!!!"
string s4 = s = s.substr(0, 6) + "World!!!!!" + s.substr(6 + 5); 不改變原有的string內容
string s = "I like C++ and C++ is powerful";
// find where "C++" is
size_t pos = s.find("C++");
// 如果不是npos (一個常數,代表沒找著)
if (pos != string::npos) {
cout << "第一次出現於: " << pos << "\n";
}string s = "123456";
s.push_back('7'); // "1234567"
s.pop_back(); // "123456"
s.pop_back(); // "12345"
cout << s; // "12345"改變原有的string內容
string s = "123";
int x = stoi(s); // string to int
double y = stod(s); // string to double
int i = 456;
string s = to_string(i); // int to string
cout << s; // 456for (int i = 0; i < s.length(); i++) {
cout << s[i];
}
for (char c : s) {
cout << c;
}vector
vector<int> v; // {}
vector<int> v(5); // {0, 0, 0, 0, 0}
vector<int> v(3, 1); // {1, 1, 1}
vector<int> v = {1, 2, 3};vector<vector<int>> v2; // {}
vector<vector<int>> v2(5); // {{}, {}, {}, {}, {}}想要多層vector,就是vector內有vector嘛
// {{0, 0}, {0, 0}, {0, 0}}
vector<vector<int>> v2(3, vector<int>(2));
// {{4, 4}, {4, 4}, {4, 4}}
vector<vector<int>> v2(3, vector<int>(2, 4));
建構子第二個參數表示內層
// 插尾
v.push_back(val) // O(1), O(n) on realloc
v.emplace_back(args)
// 在it插入val,回傳val的it
v.insert(it, val) // O(n) worst
v.emplace(it, args)
// 在it插入n個val,回傳第一個val的it
v.insert(it, n, val); // O(n + n(move))
// 在it插入[itfirst, itend),回傳第一個val的it
v.insert(it, itbegin, itend); // O(n + m)增
// 刪尾
v.pop_back() // O(1)
// 刪除it的元素,回傳下一個有效iterator
v.erase(it) // O(n) worst
// 刪除[itfirst, itend),回傳下一個有效it
s.erase(itfirst, itend) // O(n)刪
// 讀取第i個
int x = v[i] // O(1)
// 安全讀取第i個
int i2 = v.at(i) // O(1)
// 讀頭
int front = v.front() // O(1)
// 讀尾
int back = v.back() // O(1)讀
// 查看是否為空
bool isEmpty = v.empty() // O(1)
// 清空
v.clear() // O(n)
// 查看大小
int size = v.size() // O(1)三個基本方法
vector<int> v = {2,1,3};
v.push_back(4);
v.push_back(5);
v.pop_back();
v[1] = 6;2
1
3
2
1
3
2
1
3
2
1
3
4
4
4
5
4
2
6
3
4
vector<int> v = {2,1,3};
v.push_back(4);
v.push_back(5);
v.pop_back();
v[1] = 6;2
1
3
2
1
3
2
1
3
2
1
3
4
4
4
5
4
2
6
3
4
*v.begin()
for (int i = 0; i < v.size(); i++) {
cout << v[i];
}
for (int i : v) {
cout << i;
}
// 這裡 auto 應該是 vector<int>
for (auto v : v2) {
for (int i : v) {
cout << i;
}
} vector<int> v = {1,2,3,4,5};
auto it = v.begin(); // 指向第1個元素
int i = *it; // 第1個元素
cout << i << "\n"; // 1
auto it2 = v.begin() + 1; // 指向第2個元素
int i2 = *it2; // 第2個元素
cout << i2 << "\n"; // 2
auto it3 = v.begin() + 2; // 指向第3個元素
*it3 = 100; //直接更改iterator指向的元素
cout << *it3; // 100
cout << v[2]; // 100接續前一篇的iterator: 例子
vector<int> v = {1,2,3,4,5};
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // 1 2 3 4 5
}
for (auto rit = v.rbegin(); rit != v.rend(); ++rit) {
cout << *rit << " "; // 5 4 3 2 1
}接續前一篇的iterator: 走訪vector
翻譯:
每個T給10個網站 + 分數
輸出最高分數的網站
#include <bits/stdc++.h>
using namespace std;
int main() {
int T,score;
cin >> T;
string s;
vector<string> c;
for (int t = 1; t <= T;t++) {
cout << "Case #" << t << ":\n";
int max = -1;
for (int i = 0; i < 10; i++) {
cin >> s >> score;
if (score >= max) {
if (score > max) {
c.clear();
}
max = score;
c.push_back(s);
}
}
for(string s : c) {
cout << s <<"\n";
}
}
}deque
deque<int> dq; // {}
deque<int> dq(5); // {0, 0, 0, 0, 0}
deque<int> dq(3, 1); // {1, 1, 1}
deque<int> dq = {1, 2, 3};deque<deque<int>> dq2; // {}
deque<deque<int>> dq2(5); // {{}, {}, {}, {}, {}}想要多層dq,就是dq內有dq嘛
// {{0, 0}, {0, 0}, {0, 0}}
deque<deque<int>> dq2(3, deque<int>(2));
// {{4, 4}, {4, 4}, {4, 4}}
deque<deque<int>> dq2(3, deque<int>(2, 4));
(與vector相同)
建構子第二個參數表示內層
// 插尾
dq.push_back(val); // O(1) amortized
dq.emplace_back(args);
// 插頭
dq.push_front(val); // O(1) amortized
dq.emplace_front(args);
// 在it插入val,回傳val的it
dq.insert(it, val) // O(n) worst
dq.emplace(it, args)
// 在it插入n個val,回傳第一個val的it
dq.insert(it, n, val); // O(n + n(move))
// 在it插入[itfirst, itend),回傳第一個val的it
dq.insert(it, itbegin, itend); // O(n + m)增 (比vector多了插頭)
// 刪尾
dq.pop_back(); // O(1)
// 刪頭
dq.pop_front(); // O(1)
// 刪除it的元素,回傳下一個有效it
dq.erase(it) // O(n) worst
// 刪除[itfirst, itend),回傳下一個有效it
dq.erase(itfirst, itend) // O(n)刪
// 讀取第i個
int i = dq[i] // 極接近O(1)
// 安全讀取第i個
int i2 = dq.at(i) // 極接近O(1)
// 讀頭
int front = dq.front() // O(1)
// 讀尾
int back = dq.back() // O(1)讀
(與vector相同)
三個基本方法
// 查看是否為空
bool isEmpty = dq.empty() // O(1)
// 清空
dq.clear() // O(n)
// 查看大小
int size = dq.size() // O(1)deque<int> dq = {2,1,3};
dq.push_back(4);
dq.push_front(5);
dq.pop_back();
dq[1] = 6;2
1
3
2
1
3
2
1
3
5
2
1
4
4
4
5
3
5
6
1
3
deque<int> dq = {2,1,3};
dq.push_back(4);
dq.push_front(5);
dq.pop_back();
dq[1] = 6;2
1
3
2
1
3
2
1
3
5
2
1
4
4
4
5
3
5
6
1
3
*dq.begin()
stack & queue
Stack:
資料結構應該都學過
Queue:
這兩個在STL中,底層都是以deque實現
push_back() / pop_back()
back()
stack<int> s; // push val
s.push(val); // O(1)
s.emplace(args);
// pop
s.pop(); // O(1)增刪
也就是deque的push_back(val)與pop_back()
// 讀取頂部元素
int i = s.top();讀
也就是deque的back()
// 查看是否為空
bool isEmpty = s.empty() // O(1)
// 查看大小
int size = s.size() // O(1)兩個基本方法
while (!s.empty()) {
s.pop();
}清空
s = stack<int>();重新建立空的stack
stack<int> s;
s.push(5);
s.push(4);
s.push(3);
s.pop();
s.push(7);5
4
5
4
3
5
5
4
s.top()
5
4
7
5
4
3
4
7
stack<int> s;
s.push(5);
s.push(4);
s.push(3);
s.pop();
s.push(7);5
4
5
4
3
5
5
4
s.top()
5
4
7
5
4
3
4
7
翻譯:
T行
Sleep: 入某人的夢
Kick: 退出一層
Test: 在誰的夢裡
#include <bits/stdc++.h>
using namespace std;
int main() {
stack<string> dreams;
int T;
cin >> T;
while (T--) {
string s;
cin >> s;
if (s == "Sleep") {
string name;
cin >> name;
dreams.push(name);
} else if(s == "Kick") {
if(!dreams.empty())
dreams.pop();
} else if(s == "Test") {
if(dreams.empty())
cout << "Not in a dream\n";
else
cout << dreams.top() <<"\n";
}
}
}push_back() / pop_front()
back() / front()
queue<int> q; // push val
q.push(val); / q.emplace(val) // O(1)
// pop
q.pop(); // O(1)增刪
也就是deque的push_back(val)與pop_front()
// 讀取 front
int front = s.front();
// 讀取 back
int back = s.back();讀
與deque相同
// 查看是否為空
bool isEmpty = q.empty() // O(1)
// 查看大小
int size = q.size() // O(1)兩個基本方法
while (!q.empty()) {
q.pop();
}清空
q = stack<int>();重新建立空的stack
queue<int> s;
s.push(5);
s.push(4);
s.push(3);
s.pop();
s.push(7);5
4
5
4
3
5
4
3
4
3
7
5
5
5
4
4
5
4
3
3
7
s.front()
s.back()
queue<int> s;
s.push(5);
s.push(4);
s.push(3);
s.pop();
s.push(7);5
4
5
4
3
5
4
3
4
3
7
5
5
5
4
4
5
4
3
3
7
s.front()
s.back()
抱歉,沒有找到簡單的題目。
set
set<int> s;#include <bits/stdc++.h>
using namespace std;
struct CompareMethod {
bool operator()(const int &a, const int &b) const {
return a > b; // 改成大到小
}
};
int main() {
set<int, CompareMethod> s = {1, 5, 3, 2, 4};
for (int x : s)
cout << x << " "; // 5 4 3 2 1
}排序方法預設是按照物件類型預設的 < 排序法,
像是 int 的 < 是 "小在前,大在後"
你可以使用自訂的排序法
// 插入val,回傳pair<iterator, bool>(val的it, 是否是新元素)
s.insert(val) // O(log n)
s.emplace(args)
// 插入[itfirst, itend)
s.insert(itbegin, itend); // O(n + m)增
// 刪除元素,回傳刪除的個數 (0 or 1)
s.erase(val) // O(log n)
// 刪除it的元素,回傳下一個有效it
s.erase(it) // O(log n)
// 刪除[first it, end it),回傳下一個有效it
s.erase(itfirst, itend) // O(log n)刪
// 回傳指向key的it,沒有的話回傳s.end()
s.find(key) // O(log n)
// 回傳key個數 (0 or 1)
s.count(key) // O(log n)
// 回傳指向 "第一個>= key的值" it
s.lower_bound(key) // O(log n)
// 回傳指向 "第一個> key的值" it
s.upper_bound(key) // O(log n)找
三個基本方法
// 查看是否為空
bool isEmpty = s.empty() // O(1)
// 清空
s.clear() // O(n)
// 查看大小
int size = s.size() // O(1)set<int> s;
s.insert(6);
s.insert(4);
s.insert(5);
s.erase(4);
s.push(7);6
6
4
5
6
4
5
6
5
6
7
6
4
4
5
5
*s.begin()
for (int i : s) {
cout << i;
}翻譯:
給你一個文章
要你把出現過的單字,字典序,小寫輸出
看到字典序應該就想到能用set放字串了吧?
#include<bits/stdc++.h>
using namespace std;
int main() {
set<string> words;
string s;
char c;
while ((c = getchar()) != EOF) {
if (isalpha(c)) {
s += tolower(c);
} else {
words.insert(s);
s = "";
}
}
words.erase("");
for(string w : words) {
cout << w << "\n";
}
}pair
能存儲兩個不同類型的值
成員: first, second
以first < 再來 second < 排序
今天假設你有個Student,有id跟name:
struct Student {
int id;
string name;
};Student s = {31, "蔡詠竣"};我,身為一個懶人,偶爾想用pair<int, string> 代替。
pair<int, string> me = {31, "蔡詠竣"};pair<int, string> p;
p.first = 31; // 更改first
p.second = "蔡詠竣"; // 更改second
pair<int, string> p2 = make_pair(31, "蔡詠竣");
pair<int, string> p3(31, "蔡詠竣");
pair<int, string> p4 = {31, "蔡詠竣"};vector<pair<int, string>> students;
students.push_back({31, "蔡詠竣"});
pair<int, string> me = students[0];
cout << me.first << " " << me.second;一樣可以放於vector內,偶爾蠻好用的。
像這樣就是一個可以random access的k-v pair。
不用寫兩個vector對著。
pair<int, string> p1 = {31, "蔡詠竣"},
p2 = {30, "張乃文"},
p3 = {42, "黃芋泥"};
vector<pair<int, string>> v{p1, p2, p3};
for (auto i : v) { // 把 pair<int, string> 用 auto 代替
cout << i.first << " " << i.second << "\n";
}
cout << "\n";
sort(v.begin(), v.end()); // 排序
for (auto i : v) {
cout << i.first << " " << i.second << "\n";
}}前面說過了,使用first < 排序
31 蔡詠竣
30 張乃文
42 黃芋泥
30 張乃文
31 蔡詠竣
42 黃芋泥tuple
能存儲>=3個不同類型的值
成員存取方式稍有不同
從第一個元素排,再來第二個,...
簡單講就是超級懶/臨時想用 可以用。
tuple<int, int, int> coord = {1, 2, 3};
int y = get<1>(coord); // 2
get<2>(coord) = 4; // coord 變成 {1, 2, 4}
vector<tuple<int,int,int>> v;
v.push_back(coord);
v.emplace_back(10, 20, 30);
for (auto &[x,y,z] : v) { // C++17 綁定大法
cout << x << " " << y << " " << z << "\n";
}map
可以想像成是set<pair<K,V>>
或是不排序的vector<V> (K是數字)
map<int, string> m;
map<int, string> m2 = {{1,"one"}, {2,"two"}};// 如果k不存在,插入{k, v},如果存在,更新v
m[k] = v; // O(log n)
// 插入p,回傳pair<iterator, bool>(p的it, 是否是新元素)
m.insert(pair<K, T> p); // O(log n)
m.emplace(k, v)
// 插入[itfirst, itend)
m.insert(itbegin, itend) // O(m log(n+m))增
// 刪除key,回傳刪除的個數 (0 or 1)
m.erase(key) // O(log n)
// 刪除it的元素,回傳下一個有效it
m.erase(it) // O(log n)
// 刪除[first it, end it),回傳下一個有效it
m.erase(itfirst, itend) // O(k log n)刪
// 回傳指向key的it,沒有的話回傳m.end()
m.find(key) // O(log n)
// 回傳key個數 (0 or 1)
m.count(key) // O(log n)
// 回傳指向 "第一個>= key的值" it
m.lower_bound(key) // O(log n)
// 回傳指向 "第一個> key的值" it
m.upper_bound(key) // O(log n)找
// 存取key為k的value
// 如果不存在,會插入{k, (default value)},並回傳value。
m[k]; // O(log n)讀
三個基本方法
// 查看是否為空
bool isEmpty = m.empty() // O(1)
// 清空
m.clear() // O(n)
// 查看大小
int size = m.size() // O(1)map<int, string> m;
m[2] = "b";
m[1] = "a";
m[3] = "c";
m.erase(2);{2,"b"}
{1,"a"}
{1,"a"}
{2,"b"}
{3,"c"}
{3,"c"}
{2,"b"}
{1,"a"}
map: 需要排序、key不知道範圍、key不是數字
vec/dq: 不用排序(排序也行),key有範圍
翻譯:
給你 英文 + 外文
再來,給 外文 要你找 英文
#include <bits/stdc++.h>
using namespace std;
int main() {
_____________________ dict;
string line, eng, foreign;
while (getline(cin, line) && line != "") {
stringstream ss(line); // 拆分 line 成兩個字串
ss >> eng >> foreign;
_____________________;
}
while (cin >> foreign) {
if (_____________________)
cout << _____________________ << "\n";
else
cout << "eh\n";
}
}通用方法
find(v.begin(), v.end(), val);查找val的it
查找val的出現次數
count(v.begin(), v.end(), val);把元素reverse
reverse(v.begin(), v.end());vector<int> v = {1, 2, 3, 4, 5};
// reverse vector
reverse(v.begin(), v.end());
for (int x : v) // 5 4 3 2 1
cout << x << " ";回傳bool, 看val在不在
binary_search(v.begin(), v.end(), val);排序
sort(v.begin(), v.end());sort(v.begin(), v.end(), [](int a, int b)) {
/*
a在b前 -> return true,反之false
*/
return a > b;
}自訂排序 (int為例)
UVA 10268,2024/10/15 CPE 題2
翻譯:
每加一個數,找一次中位數
#include <bits/stdc++.h>
using namespace std;
int main() {
int i;
vector<int> v;
while(cin >> i) {
v.push_back(i);
sort(v.begin(), v.end());
if(v.size() % 2 == 1) {
cout << v[v.size()/2] << "\n";
} else {
cout << (v[v.size()/2] + v[v.size()/2-1])/2 << "\n";
}
}
}一些utilties
bool b = isalpha(c);
bool b = isdigit(c);
c = toupper(c);
c = tolower(c);int gcd = __gcd(a, b);
int lcm = lcm(a, b);string s = "10110101";
bitset<8>(s).to_ulong();bitset也是STL容器之一,我覺得還不用細講。
int i = 12345;
bitset<32>(i).to_string();質數表
從我大一到大三,這題出現過兩次了
其實是反質數表
int size = 1000001;
bool notprime[1000001] = {};
notprime[0] = true;
notprime[1] = true;
int lim = sqrt(size);
for (int i = 2; i <= lim; i++) {
if (!notprime[i]) {
int k = i * i;
while(k < size) {
notprime[k] = true;
k += i;
}
}
}
// 看100是不是質數
bool isPrime = !notprime[100];2025/05/20 CPE 題4
翻譯:
給多個n (T)
找n = a + b,a <= b,a和b都是質數
題解過長
最後
謝謝各位。