Loading

再次无聊2023.10.19

0x00. IO交互题——快速入门

参考博客

个人认为对构造题有帮助,毕竟 \(\text{IO}\) 交互和构造基本是一个东西。


CF679A Bear and Prime 100

题意:一个数 \(x\in[2,100]\),你可以进行不超过 \(20\) 次询问,每次询问一个 \([2,100]\) 的数,交互库给出其是否为 \(x\) 的约数,试判断 \(x\) 是否为合数


不难想到利用质因数询问。

一个 \([2,100]\) 合数,至少有一个 \(\le 10\) 的质因数,所以先询问 \(2,3,5,7\)

问出一个质因数后,我们不需要再问 \(>50\) 的质因数。

然后依次询问每个质因数即可,注意 \(4,9,25,49\) 的情况。


CF1167B Lost Numbers

题意:一个由 \(4,8,15,16,23,42\) 组成的排列 \(P\),你可以进行不超过 \(4\) 次询问,每次可以问两个数 \(P_i,P_j\) 的乘积,找出这个排列。


不难发现任意两个不同数的乘积不同,于是一个询问即可得出这两个数分别是多少,但我们无法确定顺序。

考虑到求出 \(P_{1...5}\) 后即可求出 \(P_6\),先去掉 \(P_6\)

不难想到询问 \((1,2),(2,3),(3,4),(4,5)\),即可。


CF1407C Chocolate Bunny

题意:一个 \(1...n\) 的排列 \(a\),每次可以询问 \(a_x\bmod a_y\) 的值,最多询问 \(2n\),找出这个排列。


对于 \((x,y)\) ,不难发现 \(a_x\bmod a_y\)\(a_y\bmod a_x\) 中总有一个数等于 \(a_x\)\(a_y\) 中的一个数。进一步的,\(\max(a_x\bmod a_y,a_y\bmod a_x)=\min(a_x,a_y)\)

于是两次询问 \((x,y),(y,x)\) 即可确定 \(\min(a_x,a_y)\)

先确定 \(\min(a_1,a_2)\),然后将未确定的数保留,继续与 \(a_3\) 进行询问。以此类推,即可得出 \(n-1\) 个数的值,剩下一个数就能立马确定。


CF1451E2 Bitwise Queries

题意:\(n\) 是一个 \(2\) 的幂(存在 \(m\) 满足 \(n=2^m\)),有一个序列(非排列)\(a_{0...n-1}\),你每次可以询问其中两个数 \(\operatorname{and}/\operatorname{or}/\operatorname{xor}\) 后的结果,至多询问 \(n+1\)。请求出整个序列。


与、或的可用信息较少,考虑用异或来获取有效信息。

询问出 \(a_0\)\(a_{1...n-1}\) 的异或结果,设为 \(b_{1...n-1}\)

我们现在只需要求出 \(a_0\) 即可求出整个序列,考虑找两个二进制下无交集的两个 \(b_x,b_y\),询问 \(a_0\) 分别与 \(a_x,a_y\)\(\operatorname{and}\) 的结果,然后就能容易确定 \(a_0\)

如果不存在这样的两个数,那么一定就会存在两个 \(b_x,b_y\) 满足 \(b_x=b_y\)。我们询问 \(b_x\operatorname{and} b_y\),一样可以得出 \(a_0\)


CF1114E Arithmetic Progression

题意:一个打乱的等差序列,你可以每次询问是否存在一个 \(>x\) 的数,或者询问 \(a_x\)。在 至多 \(60\) 次询问 内求出原等差数列的首项和公差。\(1\le n\le 10^6,\space 1\le a_i\le 10^9\)


先二分出末项。

然后考虑随机化,随机选择 \(a\) 中一些数,求两两差值 \(\text{gcd}\) 即可。

0x01. 非常无聊

CF1552G A Serious Referee

题意:有 \(n\) 个数 \(a_{1...n}\),以及 \(m\) 次操作。每次给出若干个位置 \(j_1,j_2,...,j_q\),表示把 \(a_{j_1},a_{j_2},...,a_{j_q}\) 升序排序。判断是否对于所有可能的序列,最终都能形成升序序列。

\(1\le n\le 40,\space 1\le k\le 10\)


套用 经典套路,所有序列都能排序的充要条件是对于所有 \(01\) 序列都能排序。

一种暴力是直接枚举 \(0...2^n-1\),时间复杂度 \(O(2^nk)\)

似乎不能折半,注意到 \(k\)\(n\) 还小很多,尝试挖性质。

每次排序操作,会调用一些新的下标,我们只关注这些新下标对应的有多少个 \(0/1\)

于是,我们只需要枚举新下标对应 \(0/1\) 个数。

一些位置上的操作可以用二进制数代替,优化时间。科普__built_popcount/__built_popcountll 帮助计算二进制下 \(1\) 的个数。

最坏情况每次操作 \(\frac nk\) 个,此时时间复杂度 \(O((\frac nk)^k)\)

CF1876D Lexichromatography

题意:一个序列 \(a_{1...n}\),给每个位置染黑/白色。需要满足,对于每个子段和每个 \(k\),其 \(a_i=k\) 的位置挖出来,黑色位置数量与白色位置数量差的绝对值 \(\le 1\);同时,黑色位置上的数连出来的子序列字典序 严格大于 白色。求方案数,模 \(998244353\)


若不考虑字典序限制,对于一种方案,每个位置颜色取反,可以得到另一种类似的方案。

考虑字典序限制,一对类似的方案,至多有一个方案合法。

但是可能一对类似的方案,两个都不合法,此时两个子序列的字典序是相同的,我们只需要算出字典序相同的方案,然后用总方案减去即可。

设总方案为 \(\text{ALL}\),字典序相同的方案为 \(\text{R}\),答案为

\[\frac {\text{ALL}-\text{R}}2 \]

先考虑计算总方案数,显然,两两值域是独立的。

差绝对值 \(\le 1\) 的限制相当于不存在 值域独立意义下 两个相邻的位置颜色相同。

发现对于每个值,贡献为 \(2\),容易计算。

然后考虑计算字典序相同的方案数。

考虑一位一位扫 \(a\) 序列,设 \(vis[x]\) 表示 \(x\) 这个值是否已加入一个子序列,而未加入另一个子序列。

当扫到一个 \(a_i\)

  • \(vis[a_i]=1\)

我们一定不能继续往相同的子序列加入 \(a_i\),这样会导致颜色相同。

维护一个队列,表示长度较大的子序列多出来的数,然后判断队首是否为 \(a_i\)

  • \(vis[a_i]=0\)

直接加入一个子序列。注意加入不同子序列有贡献,发现这个贡献不是简单的 \(2\)

比如一开始先加入 \(1,2\),贡献为 \(2\)

之后某一时刻加入 \(3,2\),我们发现 \(2\) 加入的子序列与之前加入的一定是相同的。

然后可以把同一时刻队列内的数用并查集合并,最后若分成了 \(w\) 个集合,贡献为 \(2^w\)

时间复杂度 \(O(n)\)

posted @ 2023-10-19 21:40  Lgx_Q  阅读(15)  评论(0编辑  收藏  举报