9.12 模拟赛(NOIP十三连测 #8)
2024--梦熊&太戈--NOIP十三连测 #8【订正】 - 比赛 - 梦熊联盟 (mna.wang)
复盘
T1 是求一个 \(\sum\)。感觉稳了。稍微打表找了找规律发现是一个递推的形式。
递推?矩乘!虽然我知道有更简单的方法,但我相信我写矩乘是不会出错的。开写!
期间发现一个很美妙的东西:\(x \bmod 2 = 1 - \dfrac{(-1)^x+1}2\)。积累下来,以后可能还会用到。
不久就写完了。但是样例输出少了 \(5\)???哦我发现我光求了 \(\left\lfloor \dfrac {2^i}3 \right \rfloor\) 还没求 \(\sum\)。将 \(3 \times 3\) 的矩阵扩成了 \(4 \times 4\) 就过了样例。
没有大样例?暴力程序只能跑 \(l, r \le 63\) 的,对拍不了。于是自己造了几个样例都过了就往后做了。
T2 是期望。有点慌,貌似只会打 \(n,m \le 5\) 的 \(40\) 分。
想到了 \(i \to b_i\) 建边。\(n\) 个点 \(n\) 条边且每个点的出度都是 \(1\),这张图是由若干个环构成的!
想到了 \(\operatorname{lcm}\),想到了环的长度的种类 \(\le 14\)(其实是 \(13\),不过问题不大)。然后是一个容斥,然后是一个简单组合数,然后做完了!
这么快想出了 T2 正解很激动。但写代码前发现最后一步容斥和组合数好像不太会算。悲。
尝试梳理了一下思路,将问题转化成了更简洁的表述方式。然后想。
有点难,但好像有点感觉。于是先写前面的代码,边写边考虑。
最后又搞了个新的容斥,好像是写完了。开始 dubug!
不是样例直接过了???手造一组也过了???手造的第二组也过了???感觉不太正常,于是直接对拍。
不出所料对拍第一组就挂了。跳跳跳。哦是一个 g 写成 f 了。改完后就对拍起来了。
比赛刚开始两小时,已经切了两道题了。这把稳了(伏笔)。
T3 感觉没啥思路,而且部分分都不太会。先来 T4。
两个值相等是简单的。但是一个值相等感觉不难但不太会做。于是先写暴力找规律。
显然啥规律也没有。于是写了前 \(50\) 分就跑路了。
回到 T3。终于推出了第一步(若 \(j < i\),那么我们可以通过若干次操作,将 \(a_i \gets a_i \operatorname{xor} a_j\) 且除 \(i\) 外的值都不变)。但 \(30\) 分的 \(n \le 10\) 好像还是打不了。\(2\) 的幂暂时也没有思路。
既然求 LIS 那肯定是 DP。想到了一个不转移太正常的 \(n^2\) 个状态的 DP(其实是正解)。转移也不难做。
然后我维护了一个集合 \(S\) 表示仅靠 \(a_1 \dots a_i\) 中的数能得到哪些异或和。但是 \(|S|\) 是 \(2^n\) 级别的。乘上 \(n^2\) 的状态和 \(n\) 的转移能做到 \(\mathcal O(2^nn^3)\) 的复杂度。可以过掉第一档!
写完后发现优化成 \(\mathcal O(2^nn^2)\) 是极易的,可以过掉第二档!有 \(50\) 分了。
尝试用这个程序计算了当 \(a_i\) 都是 \(2\) 的幂时的答案,发现都是 \(n\)。大胆猜测这个部分分输出 \(n\) 就行。有 \(70\) 分了!
然后结束了。
笑话来了:
-
预计 \(100+100+70+50=320\)。赢!
-
实际 \(100+60+20+20=200\)????????????????????????????????????????
赛后发现挂分原因分别是:
- T2:没开 long long;
- T3:开了 long long,但是 INF 设成了 1e9;
- T4:没开 long long。
好好好 long long 给我炸 \(120\) 分是吧。
总结
好的:
-
T1 的矩乘没挂。
-
想出了 T2 正解。
-
想出了 T3 的 \(50\)。而且加上线性基就是正解。
不好的:
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
- 被 long long 炸了 \(120\) 分。
知识点
- T1:数学,(矩阵乘法)
- T2:数学,DP,(图论),容斥,组合数。
- T3:DP,线性基。
- T4:DP。
题解
A. F
题意:求 \(\sum\limits_{i=l}^r \left\lfloor \dfrac {2^i}3 \right \rfloor\)。\(r \le 10^{18}\)。
首先差分。
令 \(f(i) = \left\lfloor \dfrac {2^i}3 \right \rfloor\)。注意到:
矩阵加速即可。
具体的,令 \(g(i) = \sum_{j=1}^i f(j)\),则矩阵:
B. la
题意:给定 \(n, m\) 和 \(1 \sim m\) 的排列 \(b\)。有一个长度为 \(n\) 的数组 \(a\),所有 \(a_i\) 的值在 \([1, m]\) 中随机。定义一次变换为同时对所有 \(i \in [1, n]\) 执行 \(a_i \gets b_{a_i}\)。求期望多少次能将所有 \(a\) 变回原样。
首先将期望转化成答案总和除以 \(m^n\)。
考虑连边 \(i \to b_i\),表示若 \(x = i\) 则 \(x\) 可以通过一次变换成为 \(b_i\)。
因为 \(b\) 是个排列,且 \(i\) 互不相同,所以图中所有点的入度和出度都为 \(1\)。也就是说整张图是由若干个环构成的。当然也包括自环。
令某个环的大小为 \(s\)。那么这个环上的任意一个点都可以通过 \(s \times k\)(\(k \in \mathbb N\))次变换回到开始。
所以若我们令 \(i\) 所在的环的大小为 \(w_i\),那么当 \(a\) 确定时答案为 \(\operatorname{lcm}(w_{a_1}, w_{a_2}, \dots, w_{a_n})\)。
暴力枚举 \(a\) 显然不行。考虑优化。
思考 \(\operatorname{lcm}\) 的性质。这个运算关注的是一个数字是否出现过,而跟这个数字出现的次数没有关系。例如 \(\operatorname{lcm}(3, 5, 7) = \operatorname{lcm}(3, 5, 7, 7, 7) \ne \operatorname{lcm}(3, 5)\)。
注意到 \(m \le 100\)。这意味着图中环的长度只有不超过 \(13\) 种。因为 \(1 + 2 + \dots + 13+14 = 105 > m\)。注意这里说的是长度的种类数而不是环的个数。
所以我们要计算的答案 \(\operatorname{lcm}(w_{a_1}, w_{a_2}, \dots, w_{a_n})\) 里,集合 \(\{w_{a_1}, w_{a_2}, \dots, w_{a_n}\}\) 的大小不超过 \(13\)。所以我们可以以 \(2^{13}\) 的复杂度枚举这个集合!算出 \(\operatorname{lcm}\) 后再算一个方案数乘起来就是答案!
具体的,我们枚举环长集合(即每种环的长度构成的集合)的子集 \(S\)。若我们能计算出有多少个 \(a\),使得每个 \(a_i\) 都满足 \(w_{a_i} \in S\),且对于每个 \(v \in S\) 都存在至少一个 \(a_i = v\)。那么这样的 \(a\) 的数量与 \(\operatorname{lcm}_{v \in S} v\) 的乘积再累加即可计算最终答案。
有点抽象。我们再明确一下当前的任务:
- 计算有多少个 \(a\),满足:
- 对于每个 \(a_i\) 都满足 \(w_{a_i} \in S\);
- 且对于每个 \(v \in S\) 都存在至少一个 \(w_{a_i} = v\)。(这个条件如果不满足就无法保证 \(\operatorname{lcm}a = \operatorname{lcm}S\)。)
我们预处理一个 \(c_i\) 表示多少 \(j\) 满足 \(i=w_j\),即有多少个点所在的环的大小为 \(i\)。
没有第二个条件很好做。答案是 \((\sum_{v \in S}c_v)^n\)。这是因为 \(a\) 的每一位都有 \(\sum_{v \in S}c_v\) 种方案。令 \(g(S) = (\sum_{v \in S}c_v)^n\)。
我们令有了第二个条件后的答案为 \(f(S)\)。那么可以容斥。即:
所以答案为:
复杂度 \(\mathcal O(3^n)\)。用于求解 \(f(S)\) 时的枚举子集。
C. z
题意:给定 \(a\)。你可以进行若干次操作,任选一个 \(i\) 并执行 \(a_i \gets a_i \operatorname{xor} a_{i-1}\)。求 LIS 的最大值。
我们断言,若 \(j < i\),那么我们可以通过若干次操作,将 \(a_i \gets a_i \operatorname{xor} a_j\) 且除 \(i\) 外的值都不变。方法是依次执行操作 \(i, i-1,\dots,j+1,\dots,i\)。
而且当 \(k < j < i\) 时,先操作 \((k, j)\) 再操作 \((j, i)\) 是没有意义的。因为这样操作等价于只操作 \((k, i)\)。
所以如果你要操作 \((j, i)\),那么 \(j\) 必须还是最初的值。
于是 \(a_i\) 最终能得到的值,是从原始的 \(a_1 \dots a_{i-1}\) 中选任意多个数异或起来,再与原始的 \(a_i\) 起来能得到的所有数。
考虑设计 DP。设 \(f(i, j)\) 表示以 \(i\) 结尾的长度为 \(j\) 的所有 LIS 里,\(a_i\) 最小是多少。
我们维护一个集合 \(S_i\) 表示仅靠 \(a_1 \dots a_i\) 中的数能得到哪些异或和。那么转移:
见 提交记录 #612373。当然可以轻易地优化成 提交记录 #612374。
当前复杂度瓶颈在于当前维护的 \(S\)。其定义是当前所有能够被凑出来的异或和。
而这恰好是线性基的定义。用线性基维护 \(S\) 即可。
往线性基内插入一个数极易。但是我们希望找到比某个值大的最小数。这个可以仿照求最大值(洛谷上的模板提)。首先我们求最大值,然后从高往低扫描整个线性基,如果减了之后仍大于 \(v\) 就减。
具体实现见 提交记录 #612531。
D. e
题意太简单不说了。
因为输入的顺序不重要,所有按照下标做 DP 是不可取的。考虑用值域 DP。
首先值域很大,首先离散化。这里离散化不去重,只算排名。
令 \(f(x, y, z)\) 表示若只考虑 \(e_i \le x, i_i \le y,\pi_i \le z\) 的人的答案,那么答案为 \(f(n,n,n)\)。
考虑 \(f(x,y,z) \to f(x+1,y,z)\) 的转移。\(f(x,y+1,x),f(x,y,z+1)\) 都是类似的。
我们首先求出那个 \(e\) 的排名为 \(x + 1\) 的位置 \(p\)。如果 \(i_p > y\) 或 \(\pi_p > z\) 那么直接忽略这个点,因为这个点无论如何都不能符合 \(f(x+1,y,z)\) 的定义,直接 \(\operatorname{chkmin}(f(x+1,y,z),f(x,y,z))\) 即可。
否则,我们让 \(i_p,\pi_p\) 分别累加到 \(y,z\) 即可。不难发现这样一定合法且最优。
代码不好写于是参考 std 提交记录 #612750