CF div3 1034(C~G)
期末周后复健第一天,一场div3只出了4道题,水平严重下滑。看来真的要加训了。。。
C
直接猜想 \(a[i]\) 是否为原序列的 前缀最小值 或 后缀最大值,满足其一即可通过做如下操作使得只剩下 \(a[i]\): 假设 \(a[i]\) 是前缀最小值:
- 对 \(a[1到i]\) 做操作1,此时新序列的第一个元素为 \(a[i]\)。
- 对除 \(a[i]\)(即新序列的第一个元素)外的整个后缀做操作2,这样整个序列只会剩下 \(2\) 个元素。
- 根据两个元素的大小关系选择合适的操作,使得 \(a[i]\) 剩下即可。
\(a[i]\) 是后缀最大值时的情况同理。
D
先考虑初始时 \(01\) 串中 \(1\) 的个数:
- \(cnt1 <= k\) -> \(Alice\) 赢
- 否则,\(Alice\) 先操作后,原串中必然会剩下若干个 \(1\)。
考虑 \(n\) 与 \(2k\) 的大小关系:
- 若 \(n >= 2k\),则长度为 \(k\) 的前缀与后缀一定互不重合,那么对于 \(Bob\) 的每一次操作:若长度为 \(k\) 的前缀中含有 \(1\),则对后缀操作;同理若长度为 \(k\) 的后缀中含有 \(1\),则对前缀操作。容易证明这样操作总是可以使得 \(Bob\) 在每次操作后字符串中 \(1\) 的数量 \(>k\)。这样 \(Alice\) 无论怎样操作都无法将字符串变为全 \(0\) 串,\(Bob\) 必赢。
- 若 \(n < 2k\),则说明长度为 \(k\) 的前缀与后缀一定存在重合的部分。那么显然对于 \(Bob\) 的每次操作,必然都会覆盖到中间这段重合的部分。那么 \(Alice\) 每次操作时尽量不对中间重合的部分操作,则 \(Bob\) 除第一次操作外,以后的每次操作可以增加 \(1\) 的净数量一定 \(<k\)。而 \(Alice\) 每次可以减少 \(1\) 的净数量一定等于 \(k\)。因此在操作过程中,\(1\) 的数量必然严格递减,最终一定可以变为全 \(0\) 串,\(Alice\) 必赢。
E
差分
遇到这种题,先考虑暴力怎么做:
对于某个 \(k\),考虑对每个数 \(x\) 检验:
若恰好删除掉 \(k\) 个数后, \(x\) 刚好成为新集合的 \(mex\),则需满足以下两个条件:
- \(x\) 能保证全部被删除:\(cnt[x] <= k\)
- 删除全部 \(x\) 后,\([0,x-1]\) 中的每个数至少需要保留一个:
化简后得到:\(n - x >= k\)
可以证明以上两个条件与 \(x\) 能成为新集合的 \(mex\) 是充要的,因此对于 \(\forall x \in[0,n]\),若 \(x \in [cnt[x],n-x]\),则 \(x\) 可以成为新集合的 \(mex\)。
显然可以差分来优化统计答案,具体细节见代码。
F
首先确定所有必须成为 \(fixed\space point\) 的点:\(i = 1\) 或 \(i\) 为质数且 \(2*i<=n\)。也就是说其他的数 \(i\) 必然存在一个 \(x<=n\),使得 \(gcd(i,x)=1\)。那么考虑将这些数全部变为非固定点,即可最大化非固定点的数量。
由于是在一个排列中作交换(即置换),因此最终一定形成若干个大小不等的环。其中大小为 \(1\) 的环为固定点,大小 \(>1\) 的环一定可以通过错位使得每个点均不是固定点。
考虑以下构造方式:先将所有 \(<=n/2\) 的质数 \(p\) 和 \(2p\) 放入同一个环中,这样就使得 \(\forall 质数p<=n/2\),均位于一个大小 \(>1\) 的置换环中。
由于所有 \(<=n/2\) 的质数均位于大小 \(>1\) 的置换环中,所有 \(>n/2\) 的质数已经钦定为固定点。因此剩下的数一定均为合数,且最大质因子显然一定 \(<=n/2\),那么由上述结论,直接把它们分配到对应最大质因子所在的环中即可。具体细节见代码。
G
数论题
首先放个结论:对于\(\forall b\space,x = (a + bk)\space mod\space m\) \(\space\) -> \(x\) 可取值是首项为 \(a\),公差为 \(gcd(k, m)\) 的等差数列。可手玩得出该结论,证明略。
剩下的题解懒得写了,大致描述下关键思路吧:由于 \(gcd(k, m)\) 一定是 \(m\) 的约数,因此对于操作1的每次修改,将 \(m\) 的每个约数均暴力处理一次,复杂度 \(O(q*d(n))\),可接受。
操作2的查询主要依据原序列的差分数组中负数的个数,因为手玩可以看出需要最小化连续非递降子数组的个数,故需要依据差分数组中的负数来分段。而单点修改最多只会改变原序列差分数组中的2个值,因此可做到修改复杂度 \(O(q*d(n))\),查询复杂度 \(O(q*log(d(n)))\)(需要二分查找对应 \(gcd\) 的下标)。具体细节见代码与视频讲解。