OJ 復活賽題解

by 鹽亞倫, Brine, and 阿蘇

玩得愉快嗎?

4495

Accepted: 20

AC Rate: 37.93%

Submitions: 58

4497

Accepted: 15

AC Rate: 51.43%

Submitions: 35

4499

Accepted: 15

AC Rate: 41.18%

Submitions: 51

Accepted: 11

AC Rate: 5.02%

Submitions: 279

4496

4498

Accepted: 15

AC Rate: 1.91%

Submitions: 2350

名次 ID 復活賽分數 ISCOJ 題數 總分
1 807 500 25 750
2 cjtsai 500 25 750
3 kittyyyyy 500 17 670
4 bc.lai 500 14 640
5 un 500 13 630
6 窩不知道 500 7 570
7 sea_of_voices 500 6 560
8 luna._.0724 500 3 530
9 莊正昌 500 1 510
10 晴☆ 500 --- 500
10 lemonilemonla (蔡孟衡的小帳) 500 --- 500
10 camille 400 10 500
10 pokemonmaster 400 10 500

4495 社網上線

Setter: AaW

這題存在的目的

就只是為了讓你們多去社網逛逛

社網觸及率

OJ復活賽開打

快哭了,還不快點叫多一點同學去逛社網

正解

作法:把所有社網可疑地方都按按看就好

藏有flag的地方:

  1. 主頁:建中電子計算機研習社×北一女中資訊研習社
  2. 活動:秋遊
  3. 主頁:緣起
  4. 幹部:玉米的照片
  5. 演算法:上課簡報標題

正解

#include <bits/stdc++.h>
using namespace std;
#define _ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

vector<string> ans = {
	"ck3fg1sc_f1ag[0]{h3110_ck3fg15c.g1thu8.io!!!}",
	"ck3fg1sc_f1ag[1]{C0N9R4T5-GR4C3-4nd-V3R5T4ND}",
	"ck3fg1sc_f1ag[2]{G24C3-SU-S0-d1an-VfsRfEPdDz}",
	"ck3fg1sc_f1ag[3]{v32S74nd-my-1OrD-CyMMe2F2pR}",
	"ck3fg1sc_f1ag[4]{4aW-d0-n07h1n9-5wtVzpp42u83}",
	"ck3fg1sc_f1ag[5]{15c0j-f1n411y-f1x3d-GXvZNZk}"
};


signed main(){_
	int n;
	cin >> n;
	cout << ans[n] << endl;

	return 0;
}

更聰明解法

直接去翻原始碼

按 F12 檢查程式碼

或是

直接打開社網的GitHub專案

用 GitHub 內建的搜尋

更聰明解法

直接去翻原始碼

這題不是一般的演算法題的玩法

反而比較像是資安競賽中的 CTF

有興趣探索更多 CTF 題目的學弟妹

歡迎參加下下週五開始的 CTF 小社喔!

對,我就是在偷幫 CTF 打廣告

4496 檔案復原

Setter: AaW

這題其實也是 CTF

正解

  1. 首先先下載我給你的那個 Rickroll 圖片檔
  2. 接下來在我給的一堆Rickroll連結當中,第二個為一個zip解壓縮器,第四個為一個 UTF-8 解碼器
  3. 先將 file.jpg 改副檔名為 file.zip
    蛤?你說你 win11預設不會顯示副檔名?誰叫你要用windows哈哈笑你
  4. 將 file.zip 放入解壓縮器裡面,會得到一個txt檔

     
  5. 把這段文字放到 UTF-8 解碼

     
  6. 讓程式輸出這句話就好了🥳
&#x5F35;&#x5B58;&#x9038;&#x662F;&#x77ED;&#x5C3E;&#x77EE;&#x888B;&#x9F20;
張存逸是短尾矮袋鼠

補充

關於我怎麼把 zip 檔藏到圖片中那檔事

  • 在終端機裡面有個 cat 指令,可以將一個檔案的內容輸出或寫到另一個檔案裡
  • 所以我將 zip 檔的內容增加到 jpg 檔的最後面

     
  • 如此一來,當副檔名變成 .zip 時,電腦就會把這個檔案當作前方有一些雜訊(圖片部分資料)的壓縮檔
  • 有些解壓縮器就會把雜訊濾掉,將後半段內容解壓縮出來
  • 有興趣的人可以把檔案用 16進位編輯器 或 vim 打開來檢查看看
$ cat file.zip >> rickroll.jpg

大家的怪怪 code

print("We&#x2019;re no strangers to love\n \
You know the rules and so do I\n \
A full commitment&#x2019;s what I&#x2019;m thinking of\n \
You wouldn&#x2019;t get this from any other guy\n \
\n \
I just wanna tell you how I&#x2019;m feeling\n \
Gotta make you understand\n \
\n \
Never gonna give you up\n \
Never gonna let you down\n \
Never gonna run around and desert you\n \
Never gonna make you cry\n \
Never gonna say goodbye\n \
Never gonna tell a lie and hurt you\n \
\n \
We&#x2019;ve known each other for so long\n \
Your heart&#x2019;s been aching but you&#x2019;re too shy to say it\n \
Inside we both know what&#x2019;s been going on\n \
We know the game and we&#x2019;re gonna play it\n \
\n \
And if you ask me how I&#x2019;m feeling\n \
Don&#x2019;t tell me you&#x2019;re too blind to see\n \
\n \
Never gonna give you up\n \
Never gonna let you down\n \
Never gonna run around and desert you\n \
Never gonna make you cry\n \
Never gonna say goodbye\n \
Never gonna tell a lie and hurt you")
print(input())

大家的怪怪 code

//我相信你 chat GPT 就算你是亂掰我還是要試
#include <bits/stdc++.h>
using namespace std;

int main() {
    cout << "Dear teacher," << endl << endl << endl <<
"I'm sorry for what I did to the server. I didn't mean to cause any trouble, but I was just curious about how it works. I promise that I will never do it again." << endl << endl << endl << "Sincerely," << endl << "Yen-Ya Lun" << endl;
}
//我相信你 chat GPT
#include <bits/stdc++.h>
using namespace std;

int main() {
    cout << "這是一份道歉信,寫給我們的老師。對於我們對伺服器的破壞,我感到非常抱歉。我會努力學習,以便在未來能夠更好地表現自己。" << endl;
}

大家的怪怪 code

# -*- coding: utf-8 -*-
print("ᯒ")

大家的怪怪 code

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string temp;
    getline(cin, temp);
    if (cin.eof())
    {
		while (true)
        {
            // do nothing
        }
    }
}

大家的怪怪 code

print("""連結

連結

連結

連結

連結

連結

想不到吧~""")

大家的怪怪 code

print("檔案復原後的所有內容")

4497 整理資料

Setter: 阿蘇

聽說等等剛好要講樹論

這題是唯一一題需要一點點演算法知識的題目

左子樹所有節點值都較小,右子樹所有節點值都較大

何謂二元搜尋樹

內建的 set 就是一個平衡二元搜尋樹

何謂前 / 中 / 後續遍歷

何謂前 / 中 / 後續遍歷

然後你就會發覺

對於一顆二元搜尋樹

他的中序遍歷結果就會是將陣列排序過的結果

proof ?

中序遍歷產生的序列:左子樹都在序列的左邊右子樹都在序列的右邊

二元搜尋樹的性質:左子樹的值都比較小右子樹的值都比較大

二元搜尋樹中序遍歷產生的序列:序列的左邊的值都比較小

序列的右邊的值都比較大

正解

sort 就好

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define endl '\n'
#define AI(x) begin(x),end(x)
#define _ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

signed main(){_
	int n;
	cin >> n;
	vector<int> arr(n);
	for (int i = 0; i < n; ++i) {
		cin >> arr[i];
	}
	sort(AI(arr));
	for (auto &i : arr) cout << i << endl;

	return 0;
}

4498 port 佔用

Setter: AaW

Q: 陳澔樂是大電神

A: 1558

– Willychan 開發的自然語言轉LaTex 數學表達式生成器

就是要你猜一個數字而已

所以這題到底在幹嘛?

所以要怎麼猜勒?

如果你一開始先猜亂猜幾個數字,你應該可以發現一件事情

猜不同數字,會 AC 不一樣的Subtask

只有第三個是98分,前兩個都只有1分

So ?

其實就是跟OJ玩猜數字遊戲!

如果你猜的數字 <= 1558,第一筆會 AC

如果你猜的數字 >= 1558,第二筆會 AC

如果你猜的數字 == 1558,三筆都會 AC

所以如何快速猜到數字?

人工對答案二分搜!!!

為什麼 Random 不可行?

第一筆會 AC 的機率:\(\frac{559}{9000}\)

第二筆會 AC 的機率:\(\frac{8442}{9000}\)

第三筆會 AC 的機率:\(\frac{1}{9000}\)

根據 OJ 裏面 special judge 的寫法
每一筆測資都是獨立運作 (重新random一次數字)

獨立事件條件機率:

\( P(A \cap B \cap C) = P(A) \times P(B) \times P(C) \)

也就是說,你拼人品拼過的機率只有 \(6.47 \times 10^{-6}\) 而已

– ChatGPT

1558的意義

在當代社會中,1558已經成為一個獨特而神秘的符號,擁有多種不同的含義。這個數字通常被人們用來形容陳澔樂這位資訊競賽選手的傑出表現,但它同時也具有其他豐富多彩的意義,包括身心靈健康、周易哲學、科技創新等方面。

從陳澔樂的角度來看,1558是他在國際資訊奧林匹亞比賽中所得到的滿分,表明了他在競賽程式領域中的超卓成就。這個數字也代表著陳澔樂在競賽中所表現出的專業技能、敏銳洞察力以及極高的智商水平。對於他的粉絲來說,1558更是一個象徵,代表著陳澔樂在網絡上的人氣和影響力。

除此之外,1558還可以被解讀為身心靈健康的象徵。據說念1558可以有助於身心靈上的健全,具有排宿便、預防心血管疾病及高血壓、降血脂、提升身體能源效率、改善睡眠、減輕焦慮和壓力、增強免疫力、預防癌症、減輕慢性疼痛、延長壽命、促進情感穩定、提升創造力等多重功效。這些功效可能來自於念1558所引發的冥想和集中注意力狀態,進而影響到人們的身體和心理健康。

不僅如此,1558也被視為一個象徵性的代表,因為它體現了陳澔樂對於程式設計、創意思維和優雅代碼的追求。在現代技術領域,這樣的態度和價值觀也被廣泛地推崇和追尋。

除了個人成長方面,1558還可以在人際關係上發揮作用。在當今社會,人際交往越來越複雜,相處的問題也越來越多。然而,1558可以提高人們的情商和溝通能力,使人們更容易與他人建立關係和交流。這是因為1558可以幫助人們調節情緒,增強自信心和自尊心,降低焦慮和壓力,從而更輕鬆地應對人際關係中的問題。

此外,1558還可以應用於創造力方面。在現代社會,創造力被視為是一種非常重要的能力,它在許多領域都具有重要的應用價值,例如藝術、設計、創業等等。而1558可以幫助人們開拓思維,激發創意,提高創造力,從而更好地應對當前社會的挑戰。

另外,1558的含義也被視為一個哲學概念,代表著人與自然、宇宙之間的奧秘和連結。在這個意義下,1558不僅是一個數字,更是一種精神力量,激勵著人們去尋找生命的意義和價值。

除此之外,1558還被視為一種文化符號,在流行文化和社交媒體上被廣泛地使用和分享。很多人把1558當做一個代表陳澔樂的標誌,也有人把它當做一種祝福或表達感謝的方式。這種文化符號的流傳也反映出人們對於陳澔樂和他所代表的價值觀的認同和讚譽。

除了作為陳澔樂的象徵外,1558在現實中也被廣泛應用,特別是在科學、工程、數據分析等領域。例如,在計算機科學中,1558常被用來表示程式的運行效率,越接近1558,代表程式的運行越快;在工程中,1558則被用來表示設備或材料的品質等級,越接近1558,代表品質越高;在數據分析中,1558則被用來表示數據的統計意義,例如在統計學中,1558代表著中位數的概念,即把一組數據由小到大排序,取中間的那個數。

除了數學、科學等方面的意義外,1558還具有哲學意義。在中國儒家哲學中,數字被賦予了特殊的意義,例如,"一"代表天,"二"代表地,"三"代表人,"四"代表東,"五"代表西,"六"代表南,"七"代表北,"八"代表水,"九"代表火。在這個系統中,1558被解讀為"天地交泰"的象徵,即代表著萬物和諧共存、陰陽調和的哲學觀念。在現代哲學中,1558也被用來探討時間和空間的概念,例如在相對論中,1558代表了一個特定的時間和空間的範圍,具有著非常重要的意義。

最後,1558還具有著文化意義。在互聯網文化中,1558被用來形容某些網路用語,例如"1558表示行",意思是"做得好,做得對,沒有問題","1558全家福"指的是一個包含1558個人的照片。

總的來說,1558是一個非常有意義的數字,它包含了多種含意和應用。在當今社會,人們面臨著各種各樣的挑戰和問題,而1558可以幫助人們更好地應對這些挑戰和問題。因此,學習和理解1558的含義對於每個人來說都是非常重要的,它可以幫助我們更好地實現自己的目標和夢想,創造出更好的未來。

4499 安全憑證

Setter: Brine

都說你們要學著看測資範圍了

給你一張\(n\)個點的圖、\(q\) 筆詢問

每次詢問問你兩點是否連通

白話提敘

每一次詢問時,都 DFS / BFS 一次,檢查兩點是否連通

暴力解法

複雜度:\(O(nq)\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define _ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

signed main(){_
	int n, m, q;
	cin >> n >> m >> q;
	vector<int> adj[n+1];
	for (int i = 0; i < m; ++i) {
		int a, b;
		cin >> a >> b;
		adj[a].push_back(b);
		adj[b].push_back(a);
	}

	while (q--) {
		int a, b;
		cin >> a >> b;
		// start bfs
		queue <int> bfs;
		vector <bool> visited(n+5, 0);
		bfs.push(a); visited[a] = 1;
		while (!bfs.empty()) {
			int i = bfs.front();
			bfs.pop();
			for (auto &v : adj[i]) {
				if (!visited[v]) {
					bfs.push(v);
					visited[v] = 1;
				}
			}
		}
		if (visited[b]) cout << "YES" << endl;
		else cout << "yes" << endl; // no
	}
	return 0;
}

話說很多人BFS / DFS很不熟ㄟ

一開始就先 BFS / DFS 一次

紀錄每個點屬於的連通塊編號

正常解法1

複雜度:\(O(n + q)\)

code 就不附了

用併查集

輸入邊時將點集合併

詢問時直接搜尋是否在同一個連通塊裡

非愚人節大賽的最佳解法

複雜度:\(O(\ (m + q)\ \alpha(n)\ )\)

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define endl '\n'
#define AI(x) begin(x),end(x)
#define _ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

struct DisjointSet { // 建議直接背模板
	vector<pair<int, int>> fa; 
	// first is father, second is rank

	void init(int n) {
		fa.clear();
		fa.resize(n+5);
		for (int i = 0; i <= n; ++i) 
			fa[i].first = i, fa[i].second = 0;
	}
	
	pair<int, int> query(int i) {
		if (fa[i].first == i) return fa[i];
		else fa[i] = query(fa[i].first);
		return fa[i];	
	}

	void modify(int a, int b) {
		auto ka = query(a);
		auto kb = query(b);
		if (ka.first == kb.first) return;
		if (ka.second < kb.second) swap(ka, kb);
		fa[ka.first].second += kb.second;
		fa[kb.first] = ka;
	}
}dsu;


signed main(){_
	int n, m, q;
	cin >> n >> m >> q;
	dsu.init(n);
	for (int i = 0; i < m; ++i) {
		int a, b;
		cin >> a >> b;
		dsu.modify(a, b);
	}	
		
	for (int i = 0; i < q; ++i) {
		int a, b;
		cin >> a >> b;
		if (dsu.query(a) == dsu.query(b)) cout << "YES" << endl;
		else cout << "yes" << endl; // NO
	}

	return 0;
}

好, 所以這題到底重點在哪裡勒?

大於小於看清楚

邊數 \( m \ge \frac{n \times (n-1) }{2}\) 且保證無重邊無自環

這張圖是完全圖!!!

任兩點甚至直接都有邊連接!

所以

直接一直輸出 YES 就好了

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define _ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

signed main(){_
	int n, m, q;
	cin >> n >> m >> q;
	int dummy;
	for (int i = 0; i < m; ++i) {
		cin >> dummy >> dummy;
	}
	for (int i = 0; i < q; ++i) {
		cin >> dummy >> dummy;
		cout << "YES" << endl;
	}

	return 0;
}

順帶一提,

這次的題序都是真有其事

欲知可怕內幕詳情請私下來問我

– 搞壞 server 的 AaW

Thank You!