Codeforces 833 题解

A

\(n\) 是奇数时恰好可以用完,\(n\) 是偶数时多出来的一块没用,所以直接输出 \((n+1)/2\) 即可。

B

每个字符出现次数都小于等于字符总数,令 \(\Sigma\) 是字符集大小,那显然有 \(|S|\le\Sigma^2\),如果大于的话根据抽屉原理,存在一个字符出现次数大于 \(\Sigma\),显然寄了,所以直接枚举就行,复杂度是 \(O(n\Sigma^2)\) 的。

C

做前缀和,称前缀和数组为 \(s\),我们把 \(a\) 根据 \(0\) 划分成多段 \([l_1,r_1],[l_2,r_2], \cdots, [l_k,r_k]\) 满足 \(a_{l_i}=0, r_i+1=l_{i+1}\),我们可以操作所有的 \(a_{l_i}\),相当于对整个后缀操作,那我们可以用 \(a_{l_i}, a_{l_{i+1}}\) 同时操作使得一段同时加上一个任意数,而答案是前缀和最多的 \(0\) 的个数,双指针+map统计每段内出现次数最多的数字即可,注意答案要加上 \([1,l_1-1]\) 段内 \(s\) 恰好是 \(0\) 的个数。

D

约定:对于 \(x,y\in N^{*}\),称 \(x \subset y\) 当且仅当 \(x|y=y\),称 \(z(x)\)\(x\) 二进制末尾 \(0\) 的个数。
直接的想法是说构造一个 \(x\) 使得 \(a|b \subset x\),并且 \(d|x\),这样 \(a|x=b|x=x\),满足题意。
观察题目发现 \(x<2^{60}\),而 \((a|b) < 2^{30}\),这启发我们直接构造 \(x=t*2^{30}+(a|b)\),其中 \(t < 2^{30}\),相当于把两个 \(2^{30}\) 以内的数 \(t\)\(a|b\) 在二进制下拼起来,接下来考虑如何构造 \(t\)
\(t\) 要满足的条件就是说 \(-t*2^{30} \equiv a|b \pmod d\)
现在唯一的问题是 \(2^{30}\) 的逆元不一定存在,但是我们发现若 \(z(d)>z(a|b)\) 一定是无解的,因为任意的 \(z(kd) \ge z(d) > z(a|b)\),故不存在 \(x=kd\)\((a|b) \subset x\),而对于 \(z(d)\le z(a|b)\) 的情况,我们直接把 \(2^{z(d)}\) 约掉,相当于 \(-t*2^{30-z(d)} \equiv \frac{a|b}{2^{z(d)}} \pmod {\frac{d}{2^{z(d)}}}\)\(t \equiv -\frac{1}{2^{30-z(d)}}\frac{a|b}{2^{z(d)}} \pmod {\frac{d}{2^{z(d)}}}\),注意其中 \({\frac{d}{2^{z(d)}}}\)\(\frac{a|b}{2^{z(d)}}\) 是直接除掉的,而 \(\frac{1}{2^{30-z(d)}}\)\(2^{30-z(d)}\) 在模 \({\frac{d}{2^{z(d)}}}\) 意义下的逆元。
赛时样例都没过,因为求逆元写了个 \((2^{30-z(d)})^{mod-2}\),实际上应该是 \((2^{30-z(d)})^{\varphi(mod)-1}\),因为 \({\frac{d}{2^{z(d)}}}\) 不一定是质数,,,,,,,比赛结束后 20 分钟才调出来,寄。

E

憨憨题,没来的及做,亏麻了。
直接建出笛卡尔树,那么显然如果 \(a,b\) 的笛卡尔树相同就是符合条件的。
考虑 dp 统计这个东西,因为 \(\sum n*m \le 10^6\),直接设计一个 \(f_{u,i}\) 表示 \(u\) 为根子树,放入数字是 \([1,i]\) 时的方案数,考虑转移,如果位置 \(u\) 放的数字不是 \(i\),这种情况的方案数就是 \(f_{u,i-1}\),如果放的是 \(i\),那么这个 \(i\) 必然是整个区间中最靠左的 \(i\),也就是左子树只能放 \([1,i-1]\),右子树可以放 \([1,i]\),把这两种方案数乘起来即可。
由上得出:

\[f_{u,i}=f_{u,i-1}+f_{lc,i-1}*f_{rc,i} \]

具体写的时候注意下空的情况,开数组的话可以搞 \(n\) 个长度为 \(m+1\) 的 vector 之类的。

F

神秘构造题,核心思想是构造一个操作 \(f(l, r)\),效果是让 \([l, r]\) 中的前一半数字 xor 上后一半数字的反转,例如 \(a_0,a_1,a_2,a_3\) 经过 \(f(0,3)\) 后变成了 \(a_0 \oplus a_3,a_1\oplus a_2,a_2,a_3\),如果有了这个操作,我们就做完了,因为对于 \(n=2k\),直接 \(f(0,n-1), f(k,k-1), f(0,n-1)\),对于 \(n=2k+1\),就 \(f(0,n-1), f(k+1, k-1), f(0,n-1)\),这个原理比较显然,可以手玩理解一下,例如 \(n=8\) 就是这样:

\(0\) \(1\) \(2\) \(3\) \(4\) \(5\) \(6\) \(7\)
\(0\oplus 7\) \(1\oplus 6\) \(2\oplus 5\) \(3\oplus 4\) \(4\) \(5\) \(6\) \(7\)
\(0\oplus 7\) \(1\oplus 6\) \(2\oplus 5\) \(3\oplus 4\) \(3\) \(2\) \(1\) \(0\)
\(7\) \(6\) \(5\) \(4\) \(3\) \(2\) \(1\) \(0\)

然后我们考虑怎么构造 \(f\),观察可以发现这个 \(f\) 的操作次数肯定是 \(O(n^2)\) 级别的,然后感性理解下,定义操作 \(L(l, r)\) 表示从 \(l+1\)\(r\) 依次异或上前一个数,\(R(l, r)\) 表示从 \(r-1\)\(l\) 以此异或上后一个数,发现我们可以 \(R(l,r), L(l+1,r), R(l+1,r-1), L(l+2,r-1), R(l+2,r-2)\cdots\),这样把整个序列变成了 \(a[0,m],a[1,m-1],a[2,m-2],\cdots,a_{\lfloor (m+1)/2 \rfloor},\cdots,a_{m-1}\)\(a[x,y]\) 表示 \([x,y]\) 中数字异或和,最后我们只需要对前一半执行一次 \(L\) 即可达到目标。

posted @ 2022-11-14 09:13  71rats  阅读(36)  评论(0编辑  收藏  举报