省选数学专题 2 做题记录
省选数学专题 2 做题记录
A CF1747E List Generation
首先考虑差分,那么我们现在就是要构造两个数组 \(a',b'\),使得 \(\sum a'=n,\sum b'=n\) 且不存在 \(i\) 使得 \(a'_i=b'_i=0\)。
考虑先枚举长度,然后计算方案数。接下来枚举 \(a'\) 中有多少个 \(>0\) 的数,把它们放进去然后用插板法计算方案数;最后再枚举 \(b'\) 中有多少个 \(>0\) 的数,此时剩下的 \(=0\) 的数必须放在上面 \(a'_i>0\) 的位置上,算出方案数之后再用插板法即可。这样的话我们的式子应该是:
最后的那个和式显然是范德蒙德卷积,所以可以化为:
现在我们有了一个 \(O(n^2)\) 的做法,考虑优化。先交换求和顺序:
然后 \((i+1)\dbinom{i}{p}\) 可以写成 \((p+1)\dbinom{i+1}{i-p}\),证明是显然的,所以继续改写为:
然后我们把后面的组合数乘积暴力展开然后重新组合,这样的话可以得到下面的结果:
改枚举 \(i\) 为 \(i-p\) 可得:
此时后面的式子可以拆出 \(\sum \binom{m}{i},\sum i\binom{m}{i}\) 以及 \(\sum i^2\binom{m}{i}\) 三个部分分别求和,这都是比较经典的组合数恒等式。然后我们就可以在 \(O(n)\) 的复杂度内求出答案了。注意求上面三个部分和的时候要预处理 \(2\) 的幂,不然的话多带个 \(\log\) 过不了。
B CF1874E Jellyfish and Hack
我们发现这个代码就是一个快速排序的假做法,每次会按照序列中第一个数的大小将序列分成两个部分然后递归。那么显然考虑利用 dp 求解。
求解前先要发现一个事情:对于长为 \(n\) 的序列,函数的运行次数最大值是 \(\dfrac{n(n+1)}{2}\)。所以考虑设 \(f(i,j)\) 表示长为 \(i\) 的序列运算总次数为 \(j\) 的方案数。这样我们的总状态数就是 \(O(n^3)\) 了,然后转移方程是简单的,枚举第一个数的大小 \(k\) 即可:
直接做是 \(O(n^6)\) 的,显然过不了。发现后面的式子非常像卷积形式,不过这样做只能优化到 \(O(n^4 \log n)\),还是过不了。这个时候我们想到只存点值,然后转移就是 \(O(n^4)\) 的了,最后我们做一下 IDFT 就可以知道系数。想法很美好但是现实很残酷,因为模数是 \(10^9+7\),不是 NTT 模数;而使用 MTT 又无法只存点值。
这个时候需要回到问题的根本,我们要的其实只是点值转系数表示的一个方法,而除了 NTT 以外还有一种方式可以完成这个任务——拉格朗日插值。所以令 \(F_i=\sum f(i,j) x^j\),我们最后求的 \(F_n\) 是一个 \(\dfrac{n(n+1)}{2}\) 次多项式,所以我们需要知道 \(\dfrac{n(n+1)}{2}+1\) 个点值进行拉格朗日插值。此时转移方程变为:
这样的话我们就可以做到 \(O(n^4)\) 转移点值了,最后做一遍拉格朗日插值即可,总复杂度 \(O(n^4)\)。不过直接写常数很大,CF 上的 32 位评测机不太能跑的过去,所以要做一些必要的优化。一个优化是我们把转移中的组合数拆到两边:
这样的话可以少算一个组合数。然后就是利用 long long
少取模,同时转移的时候可以优化掉 \(\dfrac 12\) 的常数,这样的话就可以跑过了。
C CF1873D Jellyfish and Miku
首先直接做不太可行,我们先考虑给定 \(a_i\) 之后的情况。令 \(f_i\) 表示 \(i\to n\) 的期望步数,那么显然有:
化简一下可以得到:
这个形式不是很直观,此时发现我们可以构造出差分形式,于是有:
令 \(g_i=f_{i-1}-f_i\),则有:
那么此时可以得到:
而我们要求的 \(f_0\) 就是 \(\sum g_i\),这个时候我们就可以很容易的设出 dp 状态:设 \(dp(i,j)\) 表示当前考虑到 \(i\),前 \(i\) 个 \(a\) 的和是 \(j\) 时的最小期望和。那么容易写出转移:
直接转移显然是 \(O(nm^2)\) 的。这个时候需要再发现一个性质:最优解一定保证 \(a_i\) 单调不降。这个可以用调整法简单证明。那么转移的时候必须要满足 \(j+k(n-i)<m\),此时合法的 \(k\) 的个数就会减少了,最后复杂度是 \(O(m^2\log m)\) 的。
D CF1835D Doctor's Brown Hypothesis
首先由于 \(x,y\) 可以互相到达,所以他们在同一个强连通分量中。所以我们可以对每个 SCC 单独求解。
现在考虑一个 SCC,此时从 \(x\to y\) 的路径应该可以写成 \(x\to y\) 的一条简单路径和若干个环的长度总和。令所有环分别长为 \(l_1,l_2,\cdots\),那么最后的路径长度应该就是 \(len+\sum a_il_i(a_i\ge 0)\)。先看后面这个部分,根据裴蜀定理可以知道,他可以拼凑出所有长度是 \(d=\gcd(l_i)\) 的倍数的路径;并且由于 \(k\ge n^3\) 非常大,所以我们是可以随便在 SCC 中绕环的,因此不必考虑无法走出的情况。
求解环长 \(\gcd\) 是一个比较经典的问题,具体可以看这道题。简单来说,我们以任意一个点为根跑一个生成树,对于任意一个非树边 \((u,v)\),我们和 \(|dep_u-dep_v+1|\) 取 \(\gcd\) 即可得出正确答案。
然后回到原来的部分,由于我们最终要求 \(len+\sum a_il_i=k\),而我们又知道 \(\sum a_il_i\) 是 \(d\) 的倍数,所以实际上我们要求的就是 \(len\equiv k\pmod d\)。另一方面,我们对于 \(x\to y\) 和 \(y\to x\) 都有这个性质,所以这两条简单路径也同余于 \(d\)。
而实际上,这两条路径模 \(d\) 的结果可以直接写成 \(dep_y-dep_x\) 以及 \(dep_x-dep_y\),因为别的路径一定可以用这两个式子加减一些环构成,而环长一定是 \(d\) 的倍数。那么此时就有 \(dep_y-dep_x\equiv dep_x-dep_y\pmod d\),也就是 \(2(dep_x-dep_y)\equiv 0\pmod d\)。此时要么 \(dep_x=dep_y\),要么 \(dep_x-dep_y =\frac{d}{2}\)。用一个桶统计一下贡献即可。复杂度 \(O(n+m)\)。
E CF1796F Strange Triples
这真的是人类能做出来的吗我请问呢?
下文中记 \(|n|\) 表示 \(n\) 的位数。根据题目中给出的式子不难得到:
接下来由于原式右边是一个没有化简的分数形式,考虑化简。令 \(g=\gcd(a,b)\),然后令 \(a=a'g,b=b'g\),则有:
然后发现式子中只有一项没有 \(a'\),同时又可以注意到化简后此时 \(a'\mid n\),所以令 \(n=n'a'\),则有:
此时 \(b',a'10^{|b|}\) 均为整数,所以后面的分数算出来也得是整数。于是令 \(n=k_1k_2\),满足 \(k_1\mid b\) 且 \(k_2\mid (10^{|n|}-1)\),同时 \(k_1\) 尽可能小,也就是把因子优先分配给 \(10^{|n|}-1\)。接下来再令 \(d,r\) 分别为两个式子除完后的商,那么可以得到:
接下来对等式两边同时取模 \(10^{|b|}\),由于 \(b'\le b< 10^{|b|}\) 所以取模对左边没有影响,那么有:
我们枚举 \(|n|\) 以及 \(10^{|n|}-1\) 的因数 \(k_2\),由于这个数形式比较特殊所以因子比较少。然后我们还需要枚举一些值,枚举 \(d\) 以及 \(|b|\),这样就可以直接算出 \(b'\),进一步算出 \(a'\) 了。\(d\) 的范围是 \(<B\) 的,所以可以接受。接下来我们需要算出关键的 \(g\) 来求出 \(a,b\) 的值。首先先估计一下 \(g\) 的范围:
当然这样直接枚举肯定还是炸,我们需要再缩小一下枚举量。发现 \(b=b'g=k_1d\),于是有 \(g=k_1\times \dfrac{d}{b'}\)。令 \(d'=\gcd(d,b')\),显然 \(g\) 是 \(d\div d'\) 的倍数,那么我们在枚举的时候保证这一点即可。
这样的话枚举量就被缩小到了一个合适的范围。接下来我们只需要还原出答案即可。然后我们需要判断一下算出来的节是否合法,主要要判断一下几个方面:
- \(a,b,n\) 是否真的在要求范围内。
- \(\gcd(a,b)\) 是否真的等于 \(g\)。
- \(\gcd(k_1,r)\) 是否等于 \(1\),因为如果不等于的话我们就可以再分一些质因子给 \(k_2\),不满足 \(k_1\) 最小了。
- \(|n|\) 是否真的是我们枚举的长度。
然后我们就做完了。复杂度分析比较困难,大概是 \(O(B\log B)\) 带上一个 \(200\) 倍的常数。
F CF2039F1 Shohag Loves Counting (Easy Version)
首先需要关注到一个重要性质:最大值一定在数组两端。原因在于我们要求所有 \(f\) 值互不相同,而为了满足 \(f(n-1)\ne f(n)\) 我们就必须要让最大值放在两边。进一步的可以得出结论:我们的数组一定是一个单谷,且数字两两不同。
然后考虑 dp,我们每次往里面加入一个最小值,这样的话新的 \(f(2)\sim f(n)\) 就是原来的 \(f(1)\sim f(n-1)\),我们只要让新的 \(f(1)\ne f(2)\) 即可,新的 \(f(1)\) 就是所有数字的 \(\gcd\)。所以设 \(dp(i,d)\) 表示当前最小值为 \(i\),所有数字的 \(\gcd=d\) 的方案数。转移非常简单:
直接做复杂度是 \(O(m^2\sqrt m)\) 的,考虑优化。优化前我们先把刷表改为填表:
先做一次后缀和优化,记 \(S(i,d)=\sum\limits_{j=i+1}^m dp(j,d)\),则有:
然后看到后面的 \(\gcd\),不难想到莫反,于是有:
这样的话再记 \(S'(i,d)=\sum S(i,dj)\),我们的方程就可以变为:
这样的话我们求解的复杂度就是 \(\sum\limits_{i=1}^m \sum\limits_{j\mid i} d(j)\),足够通过了。最后还需要注意上面我们其实还没有保证 \(f(1)\ne f(2)\),这个是容易的,只需要在最后把 \(S(i, d)\) 减掉即可。
G CF285E Positions in Permutations
看到题面中出现了恰好这个条件,不难联想到二项式反演。令 \(F(i)\) 表示完美数恰为 \(i\) 的排列个数,\(G(i)\) 表示钦定了完美数恰为 \(i\) 的排列个数。容斥式子是简单的,现在考虑怎样求 \(G(i)\)。
这个可以考虑 dp,设 \(dp(i,j,0/1,0/1)\) 表示当前考虑到第 \(i\) 个位置,当前完美度为 \(j\),第 \(i\) 位和第 \(i+1\) 位是否已经有数字被填上了。转移的话暴力枚举后两维的值然后转移即可,并不困难。最后有 \(G(i)=dp(n,i,*,0)\times (n-i)!\),代到容斥式子中求解即可。复杂度 \(O(n^2)\)。
H CF1774G Segment Covering
对于线段问题,有一个经典套路是我们只保留相交或包含中的一种关系,这样前者可以保证左右端点均递增,后者可以构造出树形结构等。对于这道题,显然保留相交关系比较合理,那么考虑如果去掉包含关系。
此时需要用到题目中给出的式子 \(f(l,r)-g(l,r)\),考虑讨论贡献,对于两条线段 \(s_1,s_2\),如果 \(s_1\) 包含 \(s_2\),那么若我们选了 \(s_1\),则 \(s_2\) 选与不选均可,这样的话它一定会分别贡献给 \(f,g\) 同样多的方案,贡献就是 \(0\)。所以我们完全不必考虑选 \(s_1\),把 \(s_1\) 删掉即可。如此我们保留下来的就只有相交关系了。
进一步的套用这个分析过程会发现,对于三条线段 \(s_1,s_2,s_3\),如果满足 \(l_1<l_2<l_3<r_1<r_2<r_3\),那么若我们选了 \(s_3\),则 \(s_2\) 选与不选均可,同理我们可以删除 \(s_2\)。这样的话我们就不可能有一条线段被两条线段并覆盖了,也就是说线段会形成两排互不相交的线段。
现在剩下的线段就是除了抵消的贡献外多出来的贡献,那么我们只需要算出在这个区间内线段的个数即可。考虑倍增,我们令 \(nxt_i\) 表示 \(i\) 之后第一条与 \(i\) 不相交的线段,那么我们找到 \(l\) 对应的线段 \(p\),从 \(p,p+1\) 分别开始倍增,通过跳的步数计算最后答案即可。注意如果最后两个点跳到了同一个位置,说明中间一定有地方是断开的,那么答案还是 \(0\)。
这样做的复杂度是 \(O(n\log n)\),可以通过。
I P6624 [省选联考 2020 A 卷] 作业题
首先看到题目中的 \(\gcd\),想到欧拉反演:
所以我们枚举一下 \(\gcd\),然后保留所有是 \(d\) 倍数的边,求出所有生成树边权和的和即可。这容易让我们联想到矩阵树定理,不过矩阵树定理求解的是生成树边权积之和,我们需要一些转化。最简单的想法是把边权放到指数上,构造 \(x^{w_i}\),不过这样的话难以操作且复杂度过高。我们采用另一种方法,把边权记为 \(w_ix+1\),这样我们只需要求出乘积的一次项系数就是边权和了。
那么这样的话我们做乘除法操作的时候就不用管二次项了,于是有如下运算规则:
- \((a+bx)(c+dx)=ac+(bc+ad)x\)。
- \(\dfrac{1}{a+bx}=\dfrac{b}{a}-\dfrac{b}{a^2} x\)。
构造出矩阵后直接高斯消元求解行列式即可,复杂度是 \(O(n^3 V)\) 的。直接跑比较紧张,我们可以用一点优化,显然只有 \(d\) 的倍数出现了至少 \(n-1\) 次时我们才需要求解,那么总的因子个数是 \(\sum \sigma_0(w_i)\),所以我们至多跑 \(\tfrac{\sum \sigma_0(w_i)}{n-1}\) 次,复杂度应该是 \(O(n^2\sum \sigma_0(w_i))\) 的,上界是一个 \(O(n^4\sqrt V)\),可以通过。
J P5605 小 A 与两位神仙
题目就是让我们求一个离散对数,用 BSGS 直接求的话复杂度是 \(O(n\sqrt m)\),显然过不了,我们需要寻找另外的办法。
发现题目中保证 \(m=p^{\alpha}\),这让我们联想到原根,因为此时 \(m\) 是必定有原根的。有原根对应就有了指标,所以我们对 \(x^a\equiv y\pmod m\) 两边同时取指标可得 \(a\gamma(x)\equiv \gamma(y)\pmod{\varphi(m)}\)。那么这个同余方程有解当且仅当 \(\gcd(\gamma(x),\varphi(m))\mid \gamma(y)\),它等价于 \(\gcd(\gamma(x),\varphi(m))\mid \gcd(\gamma(y),\varphi(m))\)。
接下来我们需要利用原根和阶的性质,根据阶的性质 \(\delta_m(a^k)=\dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)}\) 可知:
那么由于 \(\gcd(\gamma(x),\varphi(m))\mid \gcd(\gamma(y),\varphi(m))\),有 \(\frac{\varphi(m)}{\gcd(\varphi(m),\gamma(y))}\mid \frac{\varphi(m)}{\gcd(\varphi(m),\gamma(x))}\),也就是 \(\delta_m(y)\mid \delta_m(x)\)。那么原方程有解就等价于这个条件,我们只需要求出这两个阶即可。
求阶的方法并不难,根据阶的性质可以知道,\(\delta_m(x)\mid \varphi(m)\),而 \(\varphi(m)=(p-1)p^{\alpha-1}\),所以我们用 Pollard-Rho 和 Miller-Rabin 分解质因数,然后利用试除法直接求出阶即可。
K P6610 [Code+#7] 同余方程
首先由于 \(p\) 是若干奇素数乘积,所以我们可以把它拆开,最后用 CRT 合并即可。根据 CRT 的结论,我们求出每一个方程的解数,然后乘起来就是总的解数。那么现在我们只需要考虑 \(p\) 是奇素数的情况即可。
我们枚举 \(a\to a^2,b\to b^2\),然后我们需要求出有多少个数的平方是我们枚举出来的结果。不难联想到利用二次剩余来表示,具体的,我们用勒让德符号可以表示出这个个数,即 \(\left(\dfrac{a}{p}\right)+1\)。那么我们就知道答案是:
然后我们知道勒让德符号是完全积性函数,同时 \(b\equiv x-a\pmod p\),所以展开可得:
又由于 \(p\) 之内的二次剩余和二次非剩余个数是一样的,所以 \(\sum \left(\dfrac{a}{p}\right)=0\),于是答案就是:
接下来根据勒让德符号的性质,我们可以把 \((ax-a^2)\) 除掉一个 \(a^2\),这样值不变,于是有:
我们知道在 \(a\) 取 \([1,p-1]\) 时,\(\dfrac{1}{a}\) 取遍 \([1,p-1]\),在 \(x\ne 0\) 时,由于 \(\gcd(x,p)=1\),所以 \(\dfrac{x}{a}\) 也取遍 \([1,p-1]\),那么上面的值就应该取遍 \([0,p-2]\)。所以这个值应该是 \(0- \left(\dfrac{p-1}{p}\right)=- \left(\dfrac{-1}{p}\right)\),所以答案就是:
当然在 \(x=0\) 时,答案就是:
那么这个式子是可以直接 \(O(1)\) 求出的,所以我们每个方程就可以 \(O(1)\) 求解了,最后把方案数相乘就是答案。