0%

2025 bnuzh 周赛-6

BNUZH-ACM 周赛 Round 6 - 洛谷 | 计算机科学教育新生态

A 置换环

Solution

显然 n=1n=1,答案是 11n=2n=2,答案是 33。由样例得知,n=3n=3 时答案为 66

继续手动枚举 n=4n=4 的情况,也容易得到答案是 1010,在 {4,3,2,1}\{4,3,2,1\} 时取得。

由此合理猜测答案是 n(n+1)2\frac{n(n+1)}{2},在序列为倒序时取得。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
int n;
cin >> n;
cout << (n + 1LL) * n / 2 << endl;
for (int i = n; i >= 1; i--)
cout << i << " ";
cout << endl;
return 0;
}

Proof

这是一个非常经典的组合优化问题。为了证明最大权值为 n(n+1)2\frac{n(n+1)}{2} 且倒序排列是最优解,我们可以将证明分为理论上界分析构造验证两个部分。

一、 理论上界的证明

我们的目标是最大化 V(A)V(A),即 nn 个循环同构排列中所有置换环的个数总和。为了方便分析,我们可以转换视角:不再去数每个图中“有多少个环”,而是去计算所有可能出现的边对总权值的“贡献”。

边的总数与分布:

考虑一个排列 AA 及其所有 n1n-1 个循环移位。

对于任意一个位置 uu (1un1 \le u \le n),随着排列的循环移位,该位置上的数值 aua_u 会遍历 11nn 的所有值恰好一次。

这意味着,如果我们把这 nn 个排列对应的 nn 张图叠加在一起,我们实际上得到了一个包含 nn 个顶点的完全有向图(包含自环)。

在这个完全有向图中,总共有 n2n^2 条有向边,且每一条边 (u,v)(u, v) 都恰好在某一个循环移位的图中出现了一次。

边对答案的贡献:

在一个置换图中,如果一个置换环的长度为 LL,那么这个环里包含 LL 条边。

我们可以认为,这 LL 条边共同贡献了 11 个环。平均下来,每一条属于长度为 LL 的环的边,对总答案的贡献是 1L\frac{1}{L}

极值分析:

要使总权值 V(A)V(A) 最大,我们需要让每条边的贡献 1L\frac{1}{L} 尽可能大,也就是要让每条边所在的环长 LL 尽可能小。

  • 自环的情况 (L=1L=1):

    对于 nn 个顶点,总共只有 nn 条可能的自环边 (i,i)(i, i)

    当边 (i,i)(i, i) 出现时,它构成一个长度为 11 的环,贡献为 11=1\frac{1}{1} = 1

    nn 条自环边必然会在 nn 次循环移位的过程中各出现一次,无法避免也无法增加。

    因此,自环部分的总贡献固定为 n×1=nn \times 1 = n

  • 非自环的情况 (L2L \ge 2):

    除去 nn 条自环边,剩下的 n2nn^2 - n 条边都是 uvu \neq v 的边。

    对于这些边,能构成的最小环长是 22(即 uvuu \to v \to u)。

    此时每条边的最大贡献是 12\frac{1}{2}

计算上界:

综上所述,理论上的最大权值为:

Vmax=(自环边数×1)+(非自环边数×12)V_{max} = (\text{自环边数} \times 1) + (\text{非自环边数} \times \frac{1}{2})

Vmax=n+n2n2=2n+n2n2=n(n+1)2V_{max} = n + \frac{n^2 - n}{2} = \frac{2n + n^2 - n}{2} = \frac{n(n+1)}{2}

二、 倒序排列的构造证明

为了证明上界是可以达到的,我们需要寻找一个排列,使得它的所有 nn 个循环移位中,所有的置换环长度都不超过 2(即不存在长度 3\ge 3 的环)。这样的置换被称为“对合”(Involution),即满足 P(P(i))=iP(P(i)) = i

我们证明倒序排列 A={n,n1,,1}A = \{n, n-1, \dots, 1\} 满足此性质。

循环移位的结构分析

设原排列为 P0={n,n1,,1}P_0 = \{n, n-1, \dots, 1\}

考虑向右循环移位 kk 次后的排列 PkP_k。这个序列在形态上会被分为两段递减的子序列:

  • 第一段(前 kk 个数): 数值从 kk 递减到 11

    对于位置 ii (1ik1 \le i \le k),其对应的数值是 pi=ki+1p_i = k - i + 1

  • 第二段(后 nkn-k 个数): 数值从 nn 递减到 k+1k+1

    对于位置 jj (k+1jnk+1 \le j \le n),其对应的数值是 pj=n(j(k+1))=n+k+1jp_j = n - (j - (k + 1)) = n + k + 1 - j

验证环长性质

我们需要验证对于任意位置 xx,应用两次置换后是否回到原点,即验证 Pk(Pk(x))=xP_k(P_k(x)) = x

  • 对于第一段的位置 ii (1ik1 \le i \le k):

    映射规则为 iki+1i \to k - i + 1

    显然,映射后的位置 ki+1k - i + 1 仍然在 [1,k][1, k] 的范围内。

    再次应用映射:

    Pk(ki+1)=k(ki+1)+1=iP_k(k - i + 1) = k - (k - i + 1) + 1 = i

    这说明第一段内的元素要么构成自环(当 i=ki+1i = k - i + 1),要么构成长度为 2 的互换环。

  • 对于第二段的位置 jj (k+1jnk+1 \le j \le n):

    映射规则为 jn+k+1jj \to n + k + 1 - j

    同理,映射后的位置仍然在 [k+1,n][k+1, n] 的范围内。

    再次应用映射:

    Pk(n+k+1j)=n+k+1(n+k+1j)=jP_k(n + k + 1 - j) = n + k + 1 - (n + k + 1 - j) = j

    这说明第二段内的元素也全部构成长度为 1 或 2 的环。

结论

由于倒序排列的每一次循环移位所生成的置换图中,所有环的长度均只有 1122,这意味着我们成功让所有非自环边都贡献了最大可能的权值 12\frac{1}{2}

因此,倒序排列 A={n,n1,,1}A = \{n, n-1, \dots, 1\} 的权值能够达到理论上界 n(n+1)2\frac{n(n+1)}{2}

证毕。

B Creating Chaos

Solution

注意到 gcd(aiaj,n)min{aiaj,n}\gcd(|a_i-a_j|,n)\le \min\{|a_i-a_j|,n\},因此尽可能使得 aiaj|a_i-a_j| 变小是一个方向。

尝试将 1k1\sim k 去除,剩下 (k+1)n(k+1)\sim n 这些连续的数字。发现 AC 了。

Code

1
2
for (int i = 1; i <= k; i++)
cout << i << ' ';

Proof

这是一个基于数论中 欧拉函数(Euler’s Totient Function) 性质的严格证明。

我们将通过转换求和公式,利用凸函数性质,证明保留连续区间能使得权值和达到理论下界。

符号定义与目标

nn 为给定的数,我们保留的数字集合为 SS,其中 S=m=nk|S| = m = n - k

我们的目标是最小化目标函数:

V(S)={x,y}S,x<ygcd(yx,n)V(S) = \sum_{\{x, y\} \subseteq S, x < y} \gcd(y - x, n)

利用欧拉函数转换目标函数

利用数论中的经典恒等式:

gcd(k,n)=dk,dnϕ(d)\gcd(k, n) = \sum_{d | k, d | n} \phi(d)

其中 ϕ(d)\phi(d) 是欧拉函数(小于等于 dd 且与 dd 互质的正整数个数),且 ϕ(d)>0\phi(d) > 0

将此恒等式代入目标函数 V(S)V(S)

V(S)={x,y}Sd(yx),dnϕ(d)V(S) = \sum_{\{x, y\} \subseteq S} \sum_{d | (y-x), d | n} \phi(d)

我们可以交换求和顺序。首先枚举 nn 的所有因子 dd,然后计算有多少对 (x,y)(x, y) 的差是 dd 的倍数:

V(S)=dnϕ(d)×(满足 yx(modd) 的数对 {x,y}S 的数量)V(S) = \sum_{d | n} \phi(d) \times \left( \text{满足 } y \equiv x \pmod d \text{ 的数对 } \{x, y\} \subseteq S \text{ 的数量} \right)

分析同余类分布

对于固定的因子 dd,为了计算上述括号内的数量,我们将集合 SS 中的元素按照模 dd 的余数分类。

crc_r 为集合 SS 中满足 xr(modd)x \equiv r \pmod d 的元素个数(其中 r{0,1,,d1}r \in \{0, 1, \dots, d-1\})。

显然,所有余数的计数之和等于集合大小:

r=0d1cr=m\sum_{r=0}^{d-1} c_r = m

在模 dd 同余的任意两个数,它们的差必然是 dd 的倍数。因此,对于固定的 dd,满足条件的数对数量为:

PairCountd(S)=r=0d1(cr2)=r=0d1cr(cr1)2\text{PairCount}_d(S) = \sum_{r=0}^{d-1} \binom{c_r}{2} = \sum_{r=0}^{d-1} \frac{c_r(c_r - 1)}{2}

现在,目标函数可以重写为:

V(S)=dnϕ(d)r=0d1cr(cr1)2V(S) = \sum_{d | n} \phi(d) \sum_{r=0}^{d-1} \frac{c_r(c_r - 1)}{2}

利用凸函数性质求下界

我们要最小化 V(S)V(S)。由于 ϕ(d)\phi(d) 总是正数,如果存在一种构造 SS,能够同时使每一项 r=0d1cr(cr1)2\sum_{r=0}^{d-1} \frac{c_r(c_r - 1)}{2} 达到最小,那么该构造必然是全局最优解。

考虑函数 f(x)=x(x1)2f(x) = \frac{x(x-1)}{2}。这是一个严格凸函数(Strictly Convex Function),因为其二阶导数 f(x)=1>0f''(x) = 1 > 0

根据琴生不等式(Jensen’s Inequality)或凸优化的基本原理:

在变量总和 cr=m\sum c_r = m 固定的情况下,要最小化凸函数之和 f(cr)\sum f(c_r),变量 crc_r 必须分布得越均匀越好

也就是说,对于任意 ri,rjr_i, r_j,计数的差值 cricrj|c_{r_i} - c_{r_j}| 不能超过 1。

理想的分布是:

  • m(modd)m \pmod d 个余数,其计数为 m/d\lceil m/d \rceil
  • 剩下的余数,其计数为 m/d\lfloor m/d \rfloor

任何打破这种均匀分布的集合(即某些余数出现次数特别多,某些特别少),都会导致 cr(cr1)2\sum \frac{c_r(c_r-1)}{2} 增大。

证明连续区间是最优解

现在我们验证连续整数集合 Scon={1,2,,m}S_{con} = \{1, 2, \dots, m\} 是否满足上述“最均匀分布”条件。

对于 SconS_{con} 中的元素,模 dd 的余数序列是:

1,2,,d1,0,1,2,1, 2, \dots, d-1, 0, 1, 2, \dots

这是一个周期为 dd 的循环序列。

当选取 mm 个连续整数时:

  1. 我们完整经历了 m/d\lfloor m/d \rfloor 个周期。
  2. 多出来的 m(modd)m \pmod d 个数会依次填充余数 1,2,1, 2, \dots

因此,在 SconS_{con} 中,对于任意因子 dd(事实上是任意整数 dd):

  • 某些余数出现了 m/d\lceil m/d \rceil 次。
  • 其他余数出现了 m/d\lfloor m/d \rfloor 次。
  • 两者之差仅为 1。

这意味着,SconS_{con} 使得每一个因子 dd 对应的项 PairCountd(S)\text{PairCount}_d(S) 都达到了理论上的数学下界

结论

由于目标函数 V(S)V(S) 是若干非负项的加权和,而连续区间 SconS_{con} 能够同时使每一项都取到在约束 S=m|S|=m 下的最小值。

因此,SconS_{con}(即保留连续的 nkn-k 个数)必然是使得 V(S)V(S) 最小的最优解。

证毕。

C Meaningless Operations

Solution

对任意的正整数 aa,二进制有 nn 位,只要 bb 的二进制每位都和 aa 相反,就有

gcd(ab,a&b)=gcd(2n1,0)=2n1\gcd(a\oplus b,a \& b)=\gcd(2^n-1,0)=2^n-1

b<ab<a 一定成立,显然 2n12^n-1gcd\gcd 的上界。

但是,当 a=2n1a=2^n-1 时,b=0b=0,不符合 [1,a1][1,a-1] 的要求。根据数据范围,这样的 aa 最多只有 2525 个,枚举并特判即可。

Code

如果超时,可以先利用此程序打表出 2525a=2n1a=2^n-1 的答案。

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
#include <bits/stdc++.h>
using namespace std;

int T, n;

void solve()
{
cin >> n;
int num = 1, flg = 0, cnt = 0, ans = 0;
while (num) {
if (!(num & 1)) {
flg = 1;
break;
}
num >>= 1;
cnt++;
}
if (flg)
cout << (1 << cnt) - 1 << endl;
else {
for (int i = 1; i < n; i++)
ans = max(ans, __gcd(n ^ i, n & i));
cout << ans << endl;
}
}

int main()
{
cin >> T;
while (T--) solve();
return 0;
}

D 取沙子游戏

Solution

注意到只要有一个人取 11,之后每次双方都只能取 11

如果剩下奇数个沙子给对方,那么只要对方下一次取 11,你就输了。换言之不能留给对方奇数的局面;自己一旦面对奇数,自己是必赢的。

因此,我们需要讨论的是一开始沙子数量为偶数的情况。这个情况下,n=2mqn=2^mq,其中 m>1m>1qq 为奇数。

我们定义 lowbit(n)lowbit(n)nn 的二进制表示中最低位的 11 所对应的值。不妨设 n=2mqn = 2^m \cdot q,其中 qq 为奇数,此时 lowbit(n)=2mlowbit(n) = 2^m

我们将证明:2mk2^m \le k,则先手必胜;否则先手必败。

首先,让我们考察当 2mk2^m \le k 时,Alice 的必胜策略。

Alice 的最佳策略是第一步取走 x=2mx = 2^m 粒沙子。这步操作是合法的,因为 2mk2^m \le k

在 Alice 取走 2m2^m 后,剩余的沙子数量变为 n2m=2m(q1)n - 2^m = 2^m(q - 1)。由于 qq 是奇数,所以 q1q-1 必然是偶数,这意味着剩余的沙子数量实际上是 2m+12^{m+1} 的倍数,即剩余沙子中包含着“偶数个” 2m2^m

接下来轮到 Bob 行动。根据规则,Bob 选取的沙子数量 yy 必须是上一轮 Alice 选取的 x=2mx = 2^m 的因数。这意味着 yy 必须是 20,21,,2m2^0, 2^1, \dots, 2^m 中的某一个。这里会出现两种情况:

第一种情况,Bob 选取了 y=2my = 2^m

此时,Bob 并没有改变游戏的“粒度”,依然维持在 2m2^m 的层级上。只要 Bob 坚持取 2m2^m,Alice 也随之取 2m2^m。由于初始沙子包含奇数个 2m2^m,且 Alice 取走了第一个,剩余偶数个。在随后的“你取一个、我取一个”的拉锯战中,Bob 总是面临剩余奇数个 2m2^m 的局面,而 Alice 总是面临剩余偶数个 2m2^m 的局面。显然,最后一个 2m2^m 将会被 Alice 取走,Alice 获胜。

第二种情况,Bob 试图改变局势,选取了更小的因数 y=2jy = 2^j (其中 j<mj < m)。

这相当于 Bob 主动将游戏的粒度从 2m2^m 降级到了 2j2^j。让我们看看这对他意味着什么:此时剩余的沙子总数是 2m+12^{m+1} 的倍数,自然也是 2j+12^{j+1} 的倍数。换言之,在以 2j2^j 为单位的新局面中,剩余沙子的份数是偶数。

此时轮到 Alice,且限制条件变为 y=2jy=2^j。这对于 Alice 来说,相当于她成为了一个新的子游戏的后手,而这个子游戏的初始沙子数量是 2j2^j 的偶数倍。根据对称性原理(或者简单的模仿策略),面对偶数份沙子的先手(此时的 Bob)是必败的,因为 Alice 只要模仿 Bob 的操作(Bob 取 zz,Alice 也取 zz)即可耗尽沙子。

综上所述,只要 Alice 第一步取走 lowbit(n)lowbit(n),无论 Bob 维持原粒度还是降低粒度,Alice 均有必胜策略。

反之,让我们考察 2m>k2^m > k 时,为何 Alice 必败。

由于 k<2mk < 2^m,Alice 无法取走 2m2^m。她只能选取一个较小的数 xxxk<2mx \le k < 2^m)。

因为 x<2mx < 2^m,所以 xx 必然无法被 2m2^m 整除,这意味着 xx 的二进制最低位 lowbit(x)lowbit(x) 一定小于 2m2^m

当 Alice 取走 xx 后,剩余沙子 nxn-x 的二进制最低位将由 xx 决定,即 lowbit(nx)=lowbit(x)lowbit(n-x) = lowbit(x)

此时局面交给了 Bob,且限制条件变为 xx。注意到 lowbit(nx)lowbit(n-x) 显然小于等于 xx,这完全符合我们前面证明的“必胜条件”。Bob 此时处于一个新局面的先手位置,面对的沙子总量 NN' 满足 lowbit(N)当前限制 xlowbit(N') \le \text{当前限制 } x

因此,Bob 可以复制 Alice 在必胜情况下的策略:取走 lowbit(nx)lowbit(n-x) 粒沙子,从而掌握游戏的控制权并最终获胜。

综上所述,Alice 能够获胜的充要条件是她有能力在第一步取走 lowbit(n)lowbit(n),即 lowbit(n)klowbit(n) \le k。证明完毕。

Code

lowbit(x)lowbit(x) 可用位运算 x & (-x) 求出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <bits/stdc++.h>
using namespace std;

int T, n, k;

void solve()
{
cin >> n >> k;
if ((n & -n) <= k)
cout << "Alice\n";
else
cout << "Bob\n";
}

int main()
{
cin >> T;
while (T--) solve();
return 0;
}