2022-10-30周赛


题目来自: 2021 Summer Petrozavodsk Camp, Day 3: IQ test (XXII Open Cup, Grand Prix of IMO)

E - Eulerian?

SOLUTION

交互题。

注意到每次问一半的话得到答案的概率是$\frac{1}{2}$,于是每次随机问一半就行,如果wa了就去买彩票吧。

CODE
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
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e6 + 10;

random_device rd;
mt19937 rng(rd());

int ask(vector<int> v){
cout << "? " << v.size();
for(int i : v) cout << " " << i;
cout << endl;
int x;
cin >> x;
return x;
}

int a[N];

void solve(){
int n;
cin >> n;
vector<int> v;
for(int i = 1; i <= n; i++) v.push_back(i), a[i] = i;
int sum = ask(v), m = n / 2;
if(~m&1) m++;
for(int i = 0; i < 29; i++){
shuffle(a + 1, a + 1 + n, rng);
v.clear();
for(int j = 1; j <= m; j++){
v.push_back(a[j]);
}
int r1 = ask(v);
v.clear();
for(int j = m + 1; j <= n; j++){
v.push_back(a[j]);
}
int r2 = ask(v);
r1 = sum + r1 - r2;
if(r1 & 1){
cout << "! NO" << endl;
return;
}
}
cout << "! YES" << endl;
}

int main(){
int T = 1;
while(T--) solve();
return 0;
}

H - Hamiltonian

SOLUTION

挺好玩的构造题,vp的时候三个人玩了一个多小时没凑出解来。

看了眼题解发现非常简单……只要构造一张满图加一条链就行。

CODE
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
#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii;

void run(int n){
printf("%d %d\n", n, n);
for(int i = 2; i <= n; i++){
printf("%d %d\n", i - 1, i);
}
printf("1 %d\n", n);
}

void run(int n, int m){
vector<pii> e;
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
e.push_back({i, j});
}
}
for(int i = n + 2; i <= n + m; i++){
e.push_back({i, i - 1});
}
e.push_back({1, n + 1});
e.push_back({n, n + m});
printf("%d %d\n", n + m, (int)e.size());
for(pii i : e){
printf("%d %d\n", i.first, i.second);
}
}

void solve(){
int k;
scanf("%d", &k);
if(k == 1){
printf("2 1\n1 2\n");
return;
}
if(k == 2){
printf("4 4\n1 3\n2 3\n3 4\n1 2\n");
return;
}
if(k <= 20){
run(k);
}else{
for(int i = 2; i <= 20; i++){
for(int j = 2; j <= 20; j++){
if(i + j > 20) break;
int res = i * (i - 1) / 2 - 1 + j - 1 + 2 * (i - 1);
if(res == k){
run(i, j);
return;
}
}
}
}
}

int main(){
int T = 1;
while(T--) solve();
return 0;
}