A
枚举长度 l,那么有解的一个必要条件是 97l≤n≤122l,其中 97 和 122 分别是 a 与 z 的 ASCII 码。
可以用 zzzzz...caaaaa 这种方式来构造,考虑把第一个字母从 a 变为 z,第二个字母从 a 变为 z,一直这样重复下去,显然这可以满足 97l∼122l 内任意的 n。
至多需要枚举 ⌊n/97⌋ 次,因此复杂度为 O(n)。
B
如果我们可以给所有距离 <d 的点连一条无向边,那么这就是一个二分图染色问题。
类比平面最近点对,令 D=⌈d/2⌉,那么按照 (⌊xi/D⌋,⌊yi/D⌋,⌊zi/D⌋) 给所有点分组。
同一组内最大距离为 23D<d,所以每一组不能有超过三个点,否则无法二分图染色;其次,同一组内的点至多与周围 53 个组内的点距离 <d,所以我们可以 O(n) 给所有点对连边。
假设一个连通的二分图内有 a 个白点,权值之积为 wa;b 个黑点,权值之积为 wb。那么 F(z)=waza+wbzb。
分治 NTT 把所有的 F 乘起来即可,复杂度 O(nlog2n)。
C
对于两个人的情况,可以查看官方题解,这里主要会对调整一次后 “边数减少” 这个事情进行说明。
令有向边 i→j 存在当且仅当 wi(Si)<wi(Sj),考虑增量构造,将 1∼m 依次分配。
-
如果当前图内没有环,也就存在一个 0 入度的点,我们直接把当前物品分配给这个点。
-
否则,假设我们找到了一个简单环 p1→p2→⋯→pk→p1,将它们的 Sp1,Sp2,…,Spk 调整为 Sp2,Sp3,…,Sp1,那么所有人的 wi(Si) 都会增加。
对于调整之前的所有边 i→j,我们将它们分为四类。
- 如果 i,j 都不在环上,那么这条边依旧存在。
- 如果 i 在环上,j 不在环上,那么这条边可能存在,也可能不存在。
- 如果 i 不在环上,j 在环上,那么这条边会向前循环移动一个位置。比如 i→p3 变为 i→p2,i→p1 变为 i→pk。
- 如果 i,j 都在环上,那么这条边向前循环移动一个位置后,可能存在也可能不存在,但是不会产生自环。比如 p1→p3 变为 p1→p2,但是 w1(S1) 本身也变大了,这条边可能不存在;但是 p1→p2 不会变成 p1→p1。
反过来看,如果调整之后存在一条边 i→j,通过上面类似的分类讨论,它一定可以对应到调整前的一条边上。
所以边数每次至少减少了 k,我们反复调整直到这个图里没有环为止。
这样的话,我们对每次新增的集合询问 n 个人对它的权值,恰好询问 nm 次。
每次新增边至多 n−1 条,每一条环边我们会以 O(n2) 的代价消掉,因此最终的复杂度 O(n3m)。
D
如果每次都可以重分配,假设有 W 个工人,我们一定会让他们去 xi 前 W 大的工厂。
但是只有当一次添加工人操作可以重分配,剩下的时间并不能重分配。
我们考虑一次 w 操作后跟着若干个 f 为一组,假设这一组内的工厂为 y1,y2,…,yk,之前的工厂为 x1,x2,…,xm,都是从大到小排序,并且有 W 个工人。
假设我们规定有 l 个工人最终被分配去这一组内的工厂,那么它们带来的利润是 ∑j(k−j+1)yj,那么我们会把 (k−j+1)yj 从大到小排序后选前 l 大的,剩下的的 W−l 个工人会选择前 W−l 大的 x。
因此我们可以把 x 离散化后存到树状数组中,每次枚举所有的 l,树状数组二分找前 W−l 大的 x 之和即可。
由于所有的 l 之和是 O(n) 的,复杂度 O(nlogn)。
E
农民获胜有两种情况,要么是 A 出完了所有的牌,要么是 B 出完。
-
如果是 B 出完了所有的牌,那么它只能在最后一次出牌时出 <pc 的单牌。
如果 B 只有一张这样的牌,那么我们的流程就是 A 将主动权传递给 B,然后 B 出完自己所有的牌。
传递主动权可以通过对子传递,也可以通过单张牌传递。如果通过单张牌传递,那么 B 不能用 <pc 的单牌接受,除非 B 只有这一张牌。
-
如果是 A 出完了所有的牌,那么我们只需要考虑 A 手中 <pc 的单牌。
存在两种情况:
- B 用一张 ≥pc 的单牌接受,然后 A 用一张更大的牌回收主动权,并且本轮结束。
- B 用一张 ≥pc 的单牌接受,然后 B 出一个对子,并且 A 回收主动权,并且本轮结束。
虽然我没有办法严谨证明,但是 B 如果不结束本回合的话,他手里的牌会更少,不会优于直接结束本轮。
这样用 set 维护,复杂度 O(nlogn)。
F
定义 dp(u,v) 表示 u→v 这个子树的 SG 值,每次 DFS 所有满足 dis(v,x)≤k 的点 x 并把相连的所有子树的 SG 值异或起来就是当前局面的 SG 值。
这里可以类似换根 DP 的处理方式在 DFS 的过程中维护当前所有子树的异或,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int sg(int u, int f);
void dfs2(int u, int f, int d, vector<int>& out, int m = 0) { for (int to: go[u]) { if (to == f) continue; m ^= sg(to, u); }
out.push_back(m); if (d >= k) return; for (int to: go[u]) { if (to == f) continue; dfs2(to, u, d + 1, out, m ^ sg(to, u)); } }
|
在一轮 DFS 结束后把 out 中的数求 MEX 就是当前子树的 SG,因此记忆化搜索即可,复杂度 O(n2)。
G
对于 n,m 其中之一是偶数的情况,可以构造出一条哈密顿回路;对于 n,m 均为奇数的情况,并不能构造出来。
但是,我们并不是真的需要一条哈密顿回路,可以构造出来只是左上角一个点会变化的回路,我能构造出来的和官方题解一样,所以图我就不放了。
对于这个构造出来的两条变化的回路,它们只有一个点是不一样的,所以根据贪吃蛇的规则,这个蛇不可能在所有格子都被铺满之前咬到自己的尾巴。
构造出来之后就可以无脑让蛇头沿着图走了,复杂度 O((nm)2)。
我在赛后让 Codex 造了一个可视化页面,有兴趣的读者可以看一下。
H
官方题解的括号匹配我没看懂,这里给出一个利用元素之和传递信息的做法。
假设 a1,a2,…,ak 是给定的 S,b1,b2,…,bn−k 是 [n]∖S,其中 a,b 均升序排序。
假设插入之后的升序数组为 a1,a2,…,ai,bj,那么我们有 bj=i+j,即 i=bj−j。
我们希望通过 ∑i=1kai+bj 得到 bj−j,于是我们选择 j=n−k−(∑i=1kai)mod(n−k)。
这样 ∑i=1kai+bj≡bj−j(modn−k),又因为 n−k>k,所以 i 可以被唯一还原出来。
复杂度 O(nlogn),瓶颈在于排序。
I
本地 DFS 可以得知,由 0∼6 构成的长度为 6 的无序数组只有 3000 个左右。
那么我们直接 30002×36 打表即可,之后可以 O(1) 回答询问。
实测直接提交打表程序也是可行的。
J
对于每一条横线,它们的代价是相同的,因此我们可以通过调整法说明从 (0,0) 到达 (ai,bj) 只会走一条竖线,但是我们无法得知走哪一条竖线。
基于上面这个观察,我们可以给出一个显然的式子:
fij=min{k≤imin{t0ai+tkbj},k>imin{2t0ak−t0ai+tkbj}}=−t0ai+min{2t0ai+(k≤imintk)bj,k>imin{2t0ak+tkbj}}
令 prei=mink≤itk,Fi(x)=mink>i{2t0ak+tkx},那么我们枚举 i=n 到 i=1 的过程中维护 Fi(x) 这个凸包。由于 ai 是单调递减的,那么 y 轴上的截距就是单调递减的,相当于我们每次用一条直线去更新这个凸包,这是可以直接用栈维护的。
具体地说,我们用线段树维护一个数组 C1,C2,…,Cm,每次更新 i 的时候从栈中获取到分界点,在分界线左边的我们进行 Cj←2t0ai+tibj。
我们再维护一个答案 A1,A2,…,Am,每次需要额外对这个凸包用直线 2t0ai+preix 找到一个分界点,左边进行 Aj←Aj+2t0ai+preibj,右边进行 Aj←Aj+Cj。
如果你无脑使用矩阵维护,是会 TLE 的,就算你循环展开了也是不行。
所以我们维护修改操作 (u,v,w,p,q,r) 表示 (Aj,bj,Cj)←(Aj+ubj+vCj+w,bj,pbj+qCj+r),然后展一下式子看两个修改操作如何进行合并即可。
这样复杂度 O(nlogn+nlogm)。
K
有加法是及其难做的,所以我们对这个式子变形得到 (a−k)(b−k)≡k2(modn)。
在模 n 意义下枚举所有的 a−k,b−k 等价于枚举所有的 a,b,因此式子可以被化简:
f(n,k)=a=0∑n−1b=0∑n−1[ab≡k2(modn)]=a=0∑n−1b=0∑n−1[(a,n)∣k2][(a,n)ab≡(a,n)k2(mod(a,n)n)]=a=0∑n−1[(a,n)∣k2](a,n)
于是就有:
k=0∑mf(n,k)=k=0∑ma=0∑n−1(a,n)[(a,n)∣k2]=g∣n∑g(k=0∑m[g∣k2])(a=0∑n−1[(a,n)=g])=g∣n∑g(k=0∑m[g∣k2])(a=1∑n[(a,n)=g])=g∣n∑g(k=0∑m[g∣k2])a=1∑n/g[(a,gn)=1]=g∣n∑g(k=0∑m[g∣k2])φ(gn)
其中 g∣k2 我们可以通过质因数分解来看:枚举所有的质数 p,那么 g∣k2 当且仅当 Vp(g)≤2Vp(k),这等价于 ⌈21Vp(g)⌉≤Vp(k),于是我们枚举 g 的时候算出 u(g)=∏pp⌈21Vp(g)⌉,那么答案可以进一步写为 ∑g∣ngφ(n/g)(⌊m/u(g)⌋+1)。
直接试除法枚举因子即可,复杂度 O(n)。
L
将 vi 从小到大排序后,设 dpij 表示前 i 个装备花 j 个硬币可以达到的期望的最大值。
接下来枚举选或不选,如果选择,那么将有 100pi 的概率为 vi,(1−100pi) 的概率为 dpi−1,j−wi,能这么转移的原因是前面的式子展开会形成相同的子结构。
类似 01 背包转移即可,可以滚动数组压掉一维,复杂度 O(nm)。
M
枚举每一条线段,再枚举所有的展品,对于每一个展品我们处理出进入和退出的点,扫描线即可,复杂度 O(nm)。