ZeroJudge April Fools Contest 2020 解題心得

這次比賽真的蠻有 April Fools 的味道

不過在 ZeroJudge 平台應該是新手居多,可能會有點適應不良,或者不知從何下手

有些題目也要一些 CTF 的基礎才可能通靈解開來

這次就來一次看清楚吧!

不負責聲明:本人不是出題者,我只是寫我的解題心得而已,要官方題解請找出題者

競賽連結 Contest

競賽連結:https://zerojudge.tw/ShowContest?contestid=3282

本人 Rank 2

本人 Rank 2/125
之前在 TIOJ 打 April Fools 也是拿很前面的名次
正常競賽不會打,只會打 April Fools = =

———————————暴雷分隔線,害怕請避難————————————

題目 Problems

pA - Hello, April Fools Day 2020

題目連結:https://zerojudge.tw/ShowProblem?problemid=e959

進來雖然看懂題目了,也寫好了,可是……「送出解答」按鈕呢?

在那裡附近右鍵打開檢查

右鍵檢查

找到送出「解答按鈕」的元素,你會發現按紐被 display: none;

找到送出解答按鈕的元素,你會發現按紐被隱藏了

雙擊編輯把 display: none; 去除

雙擊編輯把 display: none; 去除

送出吧!

Done

1
print('Hello, April Fools Day 2020')

pB - 顛倒

題目連結:https://zerojudge.tw/ShowProblem?problemid=e960

整個敘述都顛倒好難看……

一秒破解,把敘述複製到無格式記事本

好,你看懂題目,也打出來了,可是送出去之後

1個AC、1個WA、2個TLE

我的聚焦會在 TLE,理當來說 $T\times N = 100\times 1000$,是不應該會 TLE

於是我就先寫其他題目了

但我後來回去再看一次標題「顛倒」

就在想,會不會輸入也要顛倒…

果然,輸入倒回去看也是正確的,只不過輸出也要顛倒輸出

示意圖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
Author: Jerry Yang C.H. (tico88612)
Date: 2020/4/1
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS() ios_base::sync_with_stdio(0);cin.tie(0)

/********** Good Luck :) **********/
int main()
{
IOS();
ll w;
int i = 0;
ll enter[1000005];
while(cin >> w){
enter[i++] = w;
}
ll ans[10000];
int j = 0;
ll t;
t = enter[--i];
while(t--){
ll n;
n = enter[--i];
ll total = 0;
while(n--){
ll tp;
tp = enter[--i];
total += tp;
}
ans[j++] = total;
}
while(j){
cout << ans[--j] << '\n';
}
return 0;
}

pC - 解題技巧

題目連結:https://zerojudge.tw/ShowProblem?problemid=e961

題目說參與「某種活動」有機會秒殺這題

再加上輸入有數字 0-9/X

就想到這題是保齡球分數計算,再稍微驗證一下輸入有 $11 \sim 21$ 字元,應該準沒錯

然後找了 UVa 584 的 Code(對,我懶得重寫

稍微改了一下,但還是 WA,不過分數多了一些

隔一段時間回來後,因為測資有誤,Rejudge 後,也直接 AC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
string line;
cin.ignore();
while (t-- && getline(cin, line)) {
if (line == "Game Over")
break;
stringstream sin(line);
vector<pair<int, int> > frame;
int n = 0, i;
for (i = 0; i < line.length(); i++) {
if (line[i] != ' ') {
line[n++] = line[i];
}
}
int score = 0;
for (i = 0; i < n; i++) {
if (line[i] == 'X') {
frame.push_back(make_pair(10, 0));
} else {
if (line[i + 1] == '/')
frame.push_back(make_pair(line[i] - '0', 10 - (line[i] - '0')));
else
frame.push_back(make_pair(line[i] - '0', line[i + 1] - '0'));
i++;
}
}
for (i = 0; i < 10; i++) {
if (frame[i].first + frame[i].second != 10)
score += frame[i].first + frame[i].second;
else if (frame[i].first == 10) {
if (frame[i + 1].first == 10)
score += 10 + 10 + frame[i + 2].first;
else
score += 10 + frame[i + 1].first + frame[i + 1].second;
} else {
score += 10 + frame[i + 1].first;
}
}
printf("%d\n", score);
}
return 0;
}

pD - 灰階

題目連結:https://zerojudge.tw/ShowProblem?problemid=e962

通靈解題失敗,等作者發題解,我覺得那公式應該是唬爛的

但我發現 Reddit 竟然找得到…

2020.04.04 更新

參考 inversion 大大的通靈的心路歷程: https://zerojudge.tw/ShowThread?postid=21040&reply=0

雖然我有看到這段話

小歐:「24bit… 就像全彩RGB那樣… ?」
小草:「你要那樣說也不是不行啦~~~」

也一度懷疑那字串不是 RGB,但那時候也不以為意(實際上就不是 RGB)

不過用 Gray Code(格雷碼)諧音梗來誤導 RGB 也太傳神w

但其實我也有發現範例輸入 #a0a0a0 顏色本身就是灰色,為何要硬轉成 #f0f0f0

只能說我的通靈之路還得加強w

本題就直接把 Hexadecimal 轉成 Binary

然後再依照這部影片的教學轉成 Gray Code(格雷碼)

再從 Binary 轉成 Hexadecimal 輸出即可 AC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
Author: Jerry Yang C.H. (tico88612)
Date: 2020/4/4
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FOR(i, j, k, in) for (int i=j ; i<k ; i+=in)
#define REP(i, j) FOR(i, 0, j, 1)
#define ALL(_a) _a.begin(),_a.end()
#define IOS() ios_base::sync_with_stdio(0);cin.tie(0)

string decToBin(int s){
string re;
REP(i, 4){
if(s % 2){
re += '1';
}
else{
re += '0';
}
s /= 2;
}
reverse(ALL(re));
return re;
}

string hexToBin(char s){
int ans = 0;
if (isdigit(s)){
ans = s - '0';
}
else {
ans = s - 'a' + 10;
}
return decToBin(ans);
}

char decToHex(int s) {
if (s < 10) {
return s + '0';
}
else {
return s - 10 + 'a';
}
}

char binToHex(string s){
int total = 0;
int now = 8, i = 0;
while (now) {
if (s[i] == '1') {
total += now;
}
i++;
now /= 2;
}
return decToHex(total);
}

/********** Good Luck :) **********/
int main()
{
IOS();
int n;
cin >> n;
while(n--){
string enter;
cin >> enter;
string a;
REP(i, 6){
a += hexToBin(enter[i]);
}
bitset<24> bita(a), bitb(a);
bitb >>= 1;
bita ^= bitb;
string bins = bita.to_string();
string ans;
for (int i = 0; i < 24; i += 4){
ans += binToHex(bins.substr(i, 4));
}
cout << ans << '\n';
}
return 0;
}

pE - 餅乾盒遊戲

題目連結:https://zerojudge.tw/ShowProblem?problemid=e963

這題你會發現,你無法從題目敘述、輸入輸出判別 Yes or No

他很強調「餅乾」

還有一句話「畢竟不同的餅乾就能代表不同的人,也就是說,能夠從餅乾來判別一個人喔。」

打過 Web CTF 就會知道,不過稍微通靈想一下

「餅乾」=「Cookies」

於是就打開 ZeroJudge 的 Cookies 欄位

Chrome按一下鎖頭

點進去,把 ZeroJudge 的 Cookies 展開,多了個東西叫做 pE_answer

pE_answer

內容蠻長的,要複製完整才有答案哦!

1
6IulIFNbaV0g54K6IOWtl+S4slMg56ysIGkg5YCL5a2X5YWD55qEIGFzY2lpIOaVuOWAvCAoRVg6IFM9ImJhciIg5YmHIFNbMF09OTgpCuS7pCBIKFMpID0gc3VtKFNbaV0qMTM5XmkpICjpgJnoo6HnmoRe5piv5oyH5pW46YGL566XKSAoRVg6IFM9ImJhciIg5YmHIEgoUyk9OTgrOTcqMTM5KzExNCoxMzleMj0yMjE2MTc1KQrlpoLmnpwgSChTKSUoU1swXSUzKzIpID09IDAgKOmAmeijoeeahCXmmK/lj5bppJjmlbgpIOWJh+ipsumkheS5vuaYr+WxrOaWvCLlsI/mrZAi55qE6aSF5Lm+77yM5Y+N5LmL5YmH5LiN5piv44CCCihFWDogUz0iYmFyIiwgIOWboOeCuiBIKFMpJShTWzBdJTMrMikgPSAyMjE2MTc1JTQgPSAzIOaVhSDoqbLppIXoqbLkuKbkuI3lsazmlrwi5bCP5q2QIueahOmkheS5vik=

結尾有個等於,看起來是 Base64 Encode,找個 Online Base64 Decoder 還原回去

1
2
3
4
若 S[i] 為 字串S 第 i 個字元的 ascii 數值 (EX: S="bar" 則 S[0]=98)
令 H(S) = sum(S[i]*139^i) (這裡的^是指數運算) (EX: S="bar" 則 H(S)=98+97*139+114*139^2=2216175)
如果 H(S)%(S[0]%3+2) == 0 (這裡的%是取餘數) 則該餅乾是屬於"小歐"的餅乾,反之則不是。
(EX: S="bar", 因為 H(S)%(S[0]%3+2) = 2216175%4 = 3 故 該餅該並不屬於"小歐"的餅乾)

知道題目了,來實作吧!

這題需要用到同餘定理,照題目先把要 MOD 的數字算出,再把 $H(S)$ 算出

算 $139$ 的次方,記得都要取 MOD,再去照題目要求判斷,即可 AC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
Author: Jerry Yang C.H. (tico88612)
Date: 2020/4/1
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define SZ(i) int(i.size())
#define FOR(i, j, k, in) for (int i=j ; i<k ; i+=in)
#define RFOR(i, j, k, in) for (int i=j ; i>=k ; i-=in)
#define REP(i, j) FOR(i, 0, j, 1)
#define IOS() ios_base::sync_with_stdio(0);cin.tie(0)

/********** Good Luck :) **********/
int main()
{
IOS();
int t;
cin >> t;
while(t--){
string s;
cin >> s;
ll mod = s[0] % 3 + 2;
ll total = 0;
ll timee = 1;
REP(i, SZ(s)){
total += ((s[i] % mod) * (timee % mod)) % mod;
timee *= 139;
timee %= mod;
}
if(total % mod == 0){
cout << "yes" << '\n';
}
else{
cout << "no" << '\n';
}
}
return 0;
}

pF - 前往疫區

題目連結:https://zerojudge.tw/ShowProblem?problemid=e964

這題賽中題目敘述爛掉,還原一下那時候的大意

「現在最嚴重的國家是…?美國
「對,如果你是從美國來的,就可以拿到提示哦!」

如果你是正常連線的話,你應該只能看到這裡

於是我就用了一下 VPN 連線到美國

小歐:「咦?? 現在這個人好像就是來自 美國 的耶」
小草:「啊… 的確呢 還真是意外耶(棒讀)」
小歐:「怎麼覺得你早就知道會有人一樣… ?」
小草:「沒那回事 那是你的錯覺♪」
小歐:「所以說那個提示.. ?」
小草:「啊,差點就忘了… 提示是『${Ans=(9487945\times\displaystyle\sum_{i=0}^{b}a^i)\bmod 10^9+7}$』。」
小歐:「我是覺得這已經不是提示的程度了啦,直接講解答還能夠算是提示嗎?? 不過確實,不看提示真的猜不到呢… …」
小草:「嘛 惡趣味可不是叫假的」
小歐:「算了… 我已經放棄思考了… …」
小草:「終於看開了呀(笑)」
小歐:「所以在最後還是來做點正事吧 在此恭喜你通過所有關卡!! 🎉🎉🎉」
小草:「不過也有可能是直接跳關到這裡就是了… ?」
小歐:「雖然相見的時間不長,但也到了該謝幕的時間了。」
小草:「我倒是覺得已經很長了… …」
小歐:「就這樣,我是主持人小歐」
小草:「我其實只是路過的♪」
小歐:「欸!? 真的假的!? 總之,有緣的話明年再見吧」
小草:「說真的,究竟有多少人能看到這裡呢… …」

然後你的背景也一起 美國 了,強烈建議連線進去捧場一下

背景也一起美國

但我是覺得不一定要連 VPN 到美國,想辦法騙過 JavaScript 是從美國來的應該也可以

回到題目重點,本題重點在這裡

$$
{Ans=(9487945\times\displaystyle\sum_{i=0}^{b}a^i)\bmod 10^9+7}
$$

$\displaystyle\sum_{i=0}^{b}a^i$ 這東西 Google 了半天,才知道那是等比級數啊!高中數學都忘光了@@

等比級數 搭配 快速冪,改一下條件判斷就 AC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
Author: Jerry Yang C.H. (tico88612)
Date: 2020/4/2
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS() ios_base::sync_with_stdio(0);cin.tie(0)

const ll MOD = 1000000007LL;

ll a;

ll q_pow(ll a, ll n, ll MOD) {
ll res = 1;
while (n) {
if (n & 1) res = res * a % MOD;
a = a * a % MOD;
n >>= 1;
}
return res % MOD;
}

ll sum(ll n) {
if (n <= 1) return a % MOD;

ll s = sum(n / 2) % MOD;

if (n % 2 == 0)
return s + s * q_pow(a, n / 2, MOD) % MOD;
else
return s + s * q_pow(a, n / 2, MOD) + q_pow(a, n, MOD) % MOD;
}

/********** Good Luck :) **********/
int main() {
IOS();
int t;
cin >> t;
while (t--) {
ll b;
cin >> a >> b;
if (a == 0) {
cout << "0" << '\n';
} else if (b == 0){
cout << "9487945" << '\n';
} else {
ll ans = sum(b);
cout << (((sum(b) + 1) % MOD) * 9487945 % MOD) % MOD << '\n';
}
}
return 0;
}

後記 Afterword

這場比賽性質不能直接跟正常比賽比較

畢竟是 April Fools 嘛 w

TCSH Online Judge 明年也可以來這樣搞好了

話說隔幾天就是 Google Code Jam 了,加上專題還有作業,估計繼續潛水了…

就醬子!ㄅㄅ!


ZeroJudge April Fools Contest 2020 解題心得
https://blog.yangjerry.tw/2020/04/03/zerojudge-april-fools-contest-2020/
作者
Jerry Yang
發布於
2020年4月3日
許可協議