Educational Codeforces Round 169 (Rated for Div. 2)

比赛链接

Problems AC
A. Closest Point
B. Game with Doors
C. Splitting Items
D. Colored Portals
E. Not a Nim Problem
F. Make a Palindrome
G. Substring Compression

A

只能是 2 个点的情况,且得有空隙插

B

分类讨论区间包含情况即可

C

策略是唯一的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void solve() {
int n = read(), k = read();

vector<int> a(n);
for (int i = 0; i < n; i++) a[i] = read();
std::sort(a.rbegin(), a.rend());

int ans = 0;
for (int i = 1; i < n; i += 2) {
int t = min(k, a[i - 1] - a[i]);
k -= t, a[i] += t;
}

for (int i = 0; i < n; i++) {
if (i % 2 == 0) ans += a[i];
else ans -= a[i];
}

cout << ans << '\n';
}

D

要么是可以直接跳,要么是向左或者向右各找一个最近的跳看看哪个小。如果不是最近的话肯定劣于最近的。预处理一下即可。

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
const std::string color = "BGRY";

int id(int x, int y) {
if (x > y) swap(x, y);
return y * (y - 1) / 2 + x;
}

void solve() {
int n = read(), q = read();

vector<std::array<int, 2>> c(n + 2);
for (int i = 1; i <= n; i++) {
string s; cin >> s;

for (int j = 0; j < 2; j++) {
c[i][j] = color.find(s[j]);
}
}

vector<std::array<int, 6>> pre(n + 1), nxt(n + 1);

for (int i = 1; i <= n; i++) {
if (i == 1) pre[i].fill(0);
else pre[i] = pre[i - 1];
pre[i][id(c[i][0], c[i][1])] = i;
}
for (int i = n; i >= 1; i--) {
if (i == n) nxt[i].fill(n + 1);
else nxt[i] = nxt[i + 1];
nxt[i][id(c[i][0], c[i][1])] = i;
}

for (int i = 0; i < q; i++) {
int x = read(), y = read();
int ans = 1e9;
if (x > y) swap(x, y);
for (auto a : c[x]) {
for (auto b : c[y]) {
if (a == b) ans = y - x;
else {
int w = id(a, b);
for (auto z : {nxt[x][w], pre[y][w]}) {
if (1 <= z and z <= n) {
ans = min(ans, abs(x - z) + abs(y - z));
}
}
}
}
}

cout << (ans == 1e9 ? -1 : ans) << "\n";
}
}

E 博弈论

给定 $n$ 堆石子,第 $i$ 堆有 $a_i$ 个。对于每次操作,玩家可以选择任意一堆石子,设其还剩 $x$ 个,若玩家可以从中取走 $y$ 个,当且仅当 $\gcd(x,y) = 1$。不能取石子的人输,问先手是否必胜。

发现每堆游戏是相对独立的,可以计算每堆的 SG 函数 值,然后将这些值进行异或运算,以判断当前状态是否为必胜(即结果是否为 $0$)

首先可以观察到 $SG(0) = 0, SG(1) = 1, SG(2) = 0$

进一步地,打表发现:质数的 $SG$ 值是连续的($2$ 除外);且合数的 $SG$ 值等于其最小质因子的 $SG$ 值。

用数学归纳法不难证明。

实现时可以考虑用线性筛,因为线性筛时每个合数会被其最小的质因数筛到。

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
std::vector<int> minp, primes, sg;
void sieve(int n) {
minp.assign(n + 1, 0), primes.clear();
sg.assign(n + 1, 0);
sg[1] = 1;
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i, primes.push_back(i);
sg[i] = primes.size();
}
sg[2] = 0;

for (auto p : primes) {
if (i * p > n) break;
minp[i * p] = p;
sg[i * p] = sg[p];
if (p == minp[i]) break;
}
}
}

void solve() {
int n = read();

int ans = 0;
for (int i = 0; i < n; i++) {
ans ^= sg[read()];
}
puts(ans ? "Alice" : "Bob");
}
Author

TosakaUCW

Posted on

2024-09-19

Updated on

2024-12-09

Licensed under

Comments