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\)。注意到:

\[\begin{aligned} f(i) &= 2 \cdot f(i-1)+1- i \bmod 2 \\ &= 2 \cdot f(i-1)+ \dfrac 12 + \dfrac{(-1)^i}2 \end{aligned} \]

矩阵加速即可。

具体的,令 \(g(i) = \sum_{j=1}^i f(j)\),则矩阵:

\[\begin{bmatrix} f(i) & 1 & (-1)^i & g(i - 1) \end{bmatrix} \times \begin{bmatrix} 2 & 0 & 0 & 1 \\ \frac 12 & -1 & 0 & 0 \\ \frac 12 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} f(i + 1) & 1 & (-1)^{i+1} & g(i) \end{bmatrix} \]

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)\)。那么可以容斥。即:

\[f(S) = \sum_{T \subseteq S} (-1)^{|S| - |T|}g(T) \]

所以答案为:

\[\sum_{S \subseteq U} f(S) \times \operatorname{lcm}_{v \in S}v \]

复杂度 \(\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\) 中的数能得到哪些异或和。那么转移:

\[f(i, j) = \min_{v \in S_{i-1}} \{v \operatorname{xor} a_i\mid \exist k, f(k, j - 1) < v \operatorname{xor} 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

posted @ 2024-09-12 13:55  2huk  阅读(2552)  评论(0编辑  收藏  举报