# Cheng的競程日記!
###### tags: `C++` `競程` `日記`
:::danger
此筆記由 @Cheng0928 編寫,請尊重作者**著作財產權**
:::
:::danger
因為 @Cheng0928 是 113 會考戰士,暫時停止更新啦!
:::
:::info
## 製作本筆記的初衷
我在準備 2023 TOI初選 跟各種競程比賽時想為自己做過的題目做點紀錄
之前我就有把各個平台我寫過的 AC code 放在 Github 上面,但光看程式碼真的有點難理解
不如把解題思路寫下來吧!
:::
:::spoiler 本文目錄
[TOC]
:::
## Who Am I
我是Cheng,本名叫潘鈺程,是個熱愛競程的國中生!
:::spoiler 興趣
* 打音遊
* 打競程
* 聽音樂
* 寫 code
* 參加各種資訊社群活動
:::
:::spoiler 比賽經歷
* NPSC 2022 國中組 初賽 第十一名
* NPSC 2022 國中組 決賽 第十八名
* AIS3 2023 EOF 參賽
* TOI 2023 初選 參賽
:::
:::spoiler 社群貢獻
* SITCON HoC 2022 台南場助教
* SCINT 北臺灣學生資訊社群負責人
:::
:::spoiler 其他個人資料
* Instagram: Weak._.Cheng0928
* APCS: 觀念3級分(68) / 實作3級分(215)
* 各大OJ暱稱: Cheng0928
* 生日: 2008/09/28
* 感情狀況: 可悲單身
:::
## 解題!
### 枚舉 --- Enumeration
#### 基本題
:::spoiler Matrix Reducing (ABC264 C)
###### tags: `位元枚舉` `矩陣`
給你高為 $H_1$ 寬為 $W_1$ 的矩陣 $A$
高為 $H_2$ 寬為 $W_2$ 的矩陣 $B$
問你是否有辦法將矩陣 $A$ 減少一些行與列來形成B矩陣
這題可利用位元枚舉的技巧來表示要刪減的行或列
AC code
```cpp
#include <bits/stdc++.h>
#define int long long //TLE or MLE remove
#define F first
#define S second
#define Cheng0928 ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define SIZE(a) signed(a.size())
using namespace std;
void sol(){
//freopen("cereal.in", "r", stdin);
//freopen("cereal.out", "w", stdout);
int ha, wa;
cin >> ha >> wa;
vector<vector<int>> A(ha, vector<int>(wa));
for(auto &v : A) for(int &it : v) cin >> it;
int hb, wb;
cin >> hb >> wb;
vector<vector<int>> B(hb, vector<int>(wb));
for(auto &v : B) for(int &it : v) cin >> it;
bool ok = 0;
for(int h = 0; h < (1 << ha); h++){
for(int w = 0; w < (1 << wa); w++){
vector<vector<int>> tmp;
for(int i = 0; i < ha; i++){
if(!((h >> i) & 1)) continue;
vector<int> col;
for(int j = 0; j < wa ; j++){
if((w >> j) & 1) col.push_back(A[i][j]);
}
tmp.push_back(col);
}
if(tmp == B) ok = 1;
}
}
if(ok) cout << "Yes\n";
else cout << "No\n";
}
signed main()
{
Cheng0928
/*int t;
cin >> t;
while(t--)*/ sol();
return 0;
}
```
:::
### 數學 --- Math
#### 基本題
:::spoiler TOI 2022 初選 A. 迷宮入口(TIOJ 2246)
###### tags: `枚舉` `記數`
設 $(u, v)$ 為詠唱的座標
每讀入一個目標點後,去枚舉以此點為中心畫的 $(2r)^2$ 方格中的座標當作 $(u, v)$
因為 $r$ 的範圍只有 $1 \leq r \leq 10$ 所以不會 TLE
那只要去計算符合條件的 $(u, v)$ 有幾個就好了
AC code
```cpp
#include <bits/stdc++.h>
#define int long long //TLE or MLE remove
#define F first
#define S second
#define Cheng0928 ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define SIZE(a) signed(a.size())
using namespace std;
int sqr(int x){
return x*x;
}
void sol(){
//freopen("cereal.in", "r", stdin);
//freopen("cereal.out", "w", stdout);
int n, r;
cin >> n >> r;
map<pair<int,int>, int> cnt;
while(n--){
int x, y;
cin >> x >> y;
for(int dx = -r; dx <= r; dx++){
for(int dy = -r; dy <= r; dy++) if(sqr(dx) + sqr(dy) <= sqr(r)) cnt[{x + dx, y + dy}]++;
}
}
int ans = 0;
for(auto it : cnt){
if(it.S & 1) ans++;
}
cout << ans << '\n';
}
signed main()
{
Cheng0928
/*int t;
cin >> t;
while(t--)*/ sol();
return 0;
}
```
:::
### 位元運算 --- Binary System
#### 基本題
:::spoiler TOI 2021 初選 A. 原始人排序(TIOJ 2193)
###### tags: `自訂排序`
做一個自訂排序函式,先判斷哪個數字的 $1$ 較多
用一個陣列去維護每個數字輸入順序
AC code
```cpp
#include <bits/stdc++.h>
#define int long long //TLE or MLE remove
#define F first
#define S second
#define Cheng0928 ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define SIZE(a) signed(a.size())
using namespace std;
int pos[1025];
bool cmp(int a, int b){
bitset<11> x, y;
x = a, y = b;
//cout << x << ' ' << y <<'\n';
if(x.count() != y.count()) return x.count() < y.count();
return pos[a] < pos[b];
}
void sol(){
//freopen("cereal.in", "r", stdin);
//freopen("cereal.out", "w", stdout);
int n;
cin >> n;
vector<int> vec(n);
int i = 0;
for(int &it : vec) cin >> it, pos[it] = i, i++;
sort(vec.begin(), vec.end(), cmp);
for(auto it = vec.begin(); it != vec.end(); it++) cout << *it << (it != prev(vec.end()) ? ' ' : '\n');
}
signed main()
{
Cheng0928
/*int t;
cin >> t;
while(t--)*/ sol();
return 0;
}
```
:::
### 貪心 --- Greedy
#### 基本題
:::spoiler Contrast (ABC178 F)
給你兩個由小排到大的序列 $A$ 與 $B$
問你是否能排出所有 $A_i \not= B_i$ 的解
從直覺來看,我們可以嘗試把 $B$ 序列反過來,盡可能的讓他們不相同
接下來我用一個範例測資來模擬一次會比較好懂
$A = 1, 2, 2, 2, 3$
$B = 1, 2, 2, 3, 3$
把 $B$ 反過來
$A = 1, 2, 2, 2, 3$
$B = 3, 3, 2, 2, 1$
我們可以發現現在序列分成三個部分
1. $A_1B_1$ 到 $A_2B_2$ :不相同
2. $A_3B_3$ 到 $A_4B_4$ :相同
3. $A_5B_5$:不相同
我們要處理的就是 $3$ 到 $4$ 的部分
但要怎麼做呢?我們可以用一個迴圈來跑相同的範圍,對這相同的數值與其他數字進行交換
但要與哪個數字交換?
設相同的數字為 $z$
那我們只要找到滿足 $A_i \not= z$ 或是 $B_i \not= z$ 的位置交換即可
AC code
```cpp
#include "bits/stdc++.h"
#define int long long //TLE or MLE remove
#define F first
#define S second
#define Cheng0928 ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define SIZE(a) signed(a.size())
using namespace std;
bool vailed(int x, int l, int r){
return x > l && x < r;
}
void sol(){
//freopen("cereal.in", "r", stdin);
//freopen("cereal.out", "w", stdout);
int n;
cin >> n;
vector<int> a(n), b(n);
for(int &it : a) cin >> it; for(int &it : b) cin >> it;
reverse(b.begin(), b.end());
int l = 0, r = -1, x;
for(int i = 0; i < n; i++){
if(a[i] == b[i]){
x = a[i];
l = r = i;
while(a[r + 1] == b[r + 1]) r++;
break;
}
}
int ptr = 0;
for(; l <= r; l++, ptr++){
while(a[ptr] == x || b[ptr] == x) ptr++;
if(ptr >= n){
cout << "No\n";
return;
}
swap(b[l], b[ptr]);
}
cout << "Yes\n";
for(int it : b) cout << it << ' ';
}///////
signed main()
{
Cheng0928
/*int t;
cin >> t;
while(t--)*/ sol();
return 0;
}
```
:::
## 競賽心得
## 社群活動心得
## 課程心得