# 競賽基本知識 Wiwi Ho ###### tags: `CRC` --- https://hackmd.io/@wiwiho/crc1082algo ![](https://i.imgur.com/KqGWkCw.png) --- # 複雜度分析 --- # 什麼是複雜度? ---- 有一個函數 $f(n)$ 它的值跟 $n$ 有什麼關係? ---- $f(n)=n^2+2n-1$ ---- $n^2$ 對 $f(n)$ 的值影響最大 $\Rightarrow$ $f(n) \in O(n^2)$ ---- ## Big-O notation 對於兩個函數 $f(n)$ 和 $g(n)$ 若存在正數 $c$ 和 $n_0$ 滿足所有的 $n \geq n_0$ 都符合 $f(n) \leq cg(n)$ 則 $f(n) \in O(g(n))$ ---- ![](https://i.imgur.com/IGmX8TO.png) ---- ## 複雜度怎麼求 只留最高次項 且把係數拿掉 ---- ## 比大小 複雜度越大 表示函數值成長越快 ---- ## 怎麼比(嚴謹定義) $\lim_{n \to \infty} \frac{g(x)}{f(x)}$ - 無限大:$O(g(n))>O(f(n))$ - $0$:$O(g(n))<O(f(n))$ - 非零常數:$O(g(n))=O(f(n))$ ---- 如果 $O(g(n))>O(f(n))$ $O(f(n)) \in O(g(n))$ $\Rightarrow 2n^2+n-1 \in O(2n^2+n-1) \in O(n^2) \in O(n^3)$ ---- 複雜度非唯一 通常會選最小而且寫出來最簡單的 --- # 用詞 ---- 常數:$O(1)$ ---- 線性:$O(n)$ ---- 其他應該很好懂 (? e.g. 對數($O(\log n)$)、根號($\sqrt{n}$)…… --- # STL 的複雜度 ---- 查表 cppreference.com --- # 時間複雜度 ---- 表示程式的執行時間如何隨輸入的數值成長 $\Rightarrow$ 用來比較演算法好壞的方法 ---- ## 會用多少時間? ---- 不能準確計算 ---- 把所有參數的最大值代入後 約 $10^8$ 到 $10^9$ 為一秒 ---- ## 範例 ---- ```cpp int n; cin >> n; vector<int> v(n); for(int i = 0; i < n; i++) cin >> v[i]; for(int i = 0; i < n - 1; i++){ //迴圈 1 for(int j = 0; j < n - i - 1; j++){ //迴圈 2 if(v[j] > v[j + 1]) swap(v[j], v[j + 1]); } } for(int i = 0; i < n; i++) cout << v[i] << " "; cout << "\n"; ``` ---- ```cpp int n; cin >> n; stack<int> st; for(int i = 0; i < n; i++){ int t; cin >> t; while(!st.empty() && st.top() <= t) st.pop(); if(st.empty()) cout << "-1 "; else cout << st.top() << " ", st.pop(); st.push(t); } cout << "\n"; ``` --- # 常數 ---- 被丟掉的常數 ---- 常數重要嗎? ---- 當然重要! ---- ```cpp for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ for(int k = 0; k < 10; k++) /*...*/; } } ``` ---- 時間複雜度 $O(n^2)$ 如果 $n \leq 10000$ $n^2=10^8$ ---- 好像勉強還行? ---- 那個 10 呢? $10n^2=10^9$ ---- 可能不太行 ---- 如果常數會造成時間剛好超過 那就很重要 ---- ## 看不到的常數 ---- 加、減、乘、除、模都是 $O(1)$ 但除和模需要比較多時間 ---- unordered_set、unordered_map 的插入刪除尋找都是 $O(1)$ 但常數很大 --- # 輸入輸出 --- # 各種流 ---- 輸入流、輸出流? ---- 什麼是流? ---- ![](https://i.imgur.com/B25QcX0.png) ---- 輸出流:把東西給它,它會負責輸出到某地方 輸入流:跟它要一個東西,它會負責從某個地方拿給你 ---- ![](https://i.imgur.com/52KjFsS.png) --- # 標準流 ---- - 標準輸入流 - cin - 標準輸出流 - cout - 標準錯誤流 - cerr ---- 預設:在 terminal 輸入輸出 可以重新導向成在檔案輸入輸出 ---- ## 錯誤流 一種輸出流 用來輸出錯誤訊息 不會被 judge 讀到 ---- ## 重新導向 ---- ## 在程式碼 ```cpp freopen("filename", "w", stdout); freopen("filename", "w", stderr); freopen("filename", "r", stdin); ``` ---- ## 在 terminal ``` command < in command > out command 2> err command < in > out 2> err command < in > out ``` ---- ## 緩衝區 ---- ## cin 輸入的東西先到緩衝區 程式讀取的時候會從緩衝區拿資料 ---- ## cout 輸出的東西先到緩衝區 flush 後再真的輸出到它該去的地方 ---- ## cerr 沒有緩衝區 會馬上輸出到它該去的地方 --- ## stringstream ---- 一種 iostream $\Rightarrow$ 是輸入流也是輸出流 ---- ```cpp stringstream ss; ss << 5; int t; ss >> t; cout << t << "\n"; ``` --- # 輸入輸出優化 ---- ![](https://i.imgur.com/gTnljTj.png) ---- 效率太差? ---- 來看看它為什麼差 ---- 輸出到 terminal 或檔案裡的常數很大 ---- ## cout 自動 flush - endl = << '\n' << flush - 使用 cin 時會自動 flush cout - 使用 cerr 時會自動 flush cout - 程式結束時強制 flush ---- - 不要用 endl - cin.tie(0) - cerr.tie(0) - 在最後讓程式自己 flush 就好了 ---- ## 歷史因素 要和 scanf/printf 同步 ---- ios_base::sync_with_stdio(false) --- # 運算子重載 ---- ```cpp ostream& operator<<(ostream& o, pair<int, int> p){ return o << p.first << " " << p.second; } istream& operator>>(istream& i, pair<int, int> p){ return i >> p.first >> p.second; } ``` --- # 輸入格式 ---- ## EOF ---- EOF = End Of Line ---- 某些題目: 一個檔案有多筆測資 而且不告訴你有幾筆 ---- ```cpp while(cin >> /*...*/){ //... } ``` ---- ## terminal 不是 file? 按 ctrl+z 或 ctrl+d 製造 EOF ---- ## 輸入一整行 ---- ```cpp string s; getline(in, s); //in 是輸入流 ``` ---- ## 跟 >> 混用 ---- ``` abc abcd abcd ``` ```cpp string a, b; cin >> a; getline(cin, b); ``` ---- 預期:a=abc,b=abcd abcd 實際:a=abc,b=空字串 ---- 多 getline 一次 ---- ## 忽略輸入 ZJ c268: 給你一堆數字,找三個數字當三角形邊長 ---- $O(n \log n)$ 可以嗎? ---- $n \leq 10^7$ 太多了吧 ---- $n \geq 50$ 保證有解 所以超過 50 項就可以不用讀了 ---- 可是一個檔案多測資,怎麼辦? ---- 把輸入忽略掉 ```cpp cin.ignore(1000000000, '\n'); ``` --- # 輸出格式 ---- ## 小數位數 ---- ```cpp cout << fixed << setprecision(10) << ...; ``` ---- ## 數字寬度 ---- ```cpp cout << setw(n) << setfill(c) << ...; ``` --- # 前置處理器 --- # 什麼是前置處理器? ---- 在編譯之前,會先做前置處理 ---- ```cpp #include ... #define ... ``` 都是前置處理器的指令 ---- ## 什麼是前置處理? 根據指令修改程式碼 ---- ## include ---- 把別的檔案的內容在該處貼上 ---- ## 引號、角括號? ```cpp #include <iostream> #include "test.cpp" ``` ---- 找檔案的地方不同 - 角括號:找函式庫 - 引號:找同個目錄 --- ## define ---- macro/ 巨集 / 宏 ---- ```cpp //#define NDEBUG #include <bits/stdc++.h> #include <bits/extc++.h> #define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define iter(a) a.begin(), a.end() #define riter(a) a.rbegin(), a.rend() #define lsort(a) sort(iter(a)) #define gsort(a) sort(riter(a)) #define mp(a, b) make_pair(a, b) #define pb(a) push_back(a) #define eb(a) emplace_back(a) #define pf(a) push_front(a) #define pob pop_back() #define pof pop_front() #define F first #define S second #define printv(a, b) {bool pvaspace=false; \ for(auto pva : a){ \ if(pvaspace) b << " "; pvaspace=true;\ b << pva;\ }\ b << "\n";} #define pii pair<int, int> #define pll pair<ll, ll> #define tiii tuple<int, int, int> #define mt make_tuple #define gt(t, i) get<i>(t) #define iceil(a, b) ((a) / (b) + !!((a) % (b))) //#define TEST typedef long long ll; typedef unsigned long long ull; using namespace std; using namespace __gnu_pbds; const ll MOD = 1000000007; const ll MAX = 2147483647; template<typename A, typename B> ostream& operator<<(ostream& o, pair<A, B> p){ return o << '(' << p.F << ',' << p.S << ')'; } int main(){ StarBurstStream return 0; } ``` ---- ```cpp #define a b ``` 把所有單字 a 換成 b ---- 也可以用 function ```cpp #define f(a) a+4 ``` ---- 換行 ```cpp #define printv(a, b) {bool pvaspace=false; \ for(auto pva : a){ \ if(pvaspace) b << " "; pvaspace=true;\ b << pva;\ }\ ``` ---- 一樣嗎? ```cpp #define f(a) a + 5 //... cout << (3 * f(1)); ``` ```cpp int f(int a){ return a + 5; } //... cout << (3 * f(1)); ``` ---- ## 條件判斷 ---- ```cpp #if ... ... #elif ... ... #else ... #endif ``` ---- 符合條件的地方才會留下來 ---- ```cpp #if defined(a) #ifdef (a) #if !defined(a) #ifndef (a) ``` 判斷 a 有沒有被 define 過 --- 去寫練習題
{"metaMigratedAt":"2023-06-15T07:31:21.673Z","metaMigratedFrom":"Content","title":"競賽基本知識","breaks":false,"contributors":"[{\"id\":\"02353542-5acb-4a66-abd0-128b1af24abb\",\"add\":6532,\"del\":11}]"}
    1017 views