数论题
trick 整合
-
根号分治在质数中非常经典的应用:对于值域进行根号分治,对 \(\le \sqrt w\) 的小质数值域不大,\(>\sqrt w\) 的大质数最多只有一个,所以各有优秀性质。
-
比如说上面那种根号分治的应用也可以用在分析数量级上。
-
公约数题目都可以分解成枚举质数的形式。还有一种要算出有多少满足 \(p\mid x\) 但是 \(p\nmid x\),这种可以用容斥算。
题目
P13568 [CCPC 2024 重庆站] 乘积,欧拉函数,求和
题目大意
有 \(n\) 个数 \(a_1,\dots,a_n\),求 \(\sum_{S\subseteq\{1,\dots,n\}} \varphi(\prod_{i\in S} a_i) \bmod 998244353\),其中空集乘积为 \(1\)。
\(1\le n\le 2000,\ 1\le a_i\le 3000\)。
解题思路
回到原式就是
我们一次考虑每个 \(a_i\) 的贡献,因为每个质因数只能供献一次,所以我们要把它是否出现过记录下来,具体来说记状态 \(f_{i,S}\) 表示前 \(i\) 个数,选出的质因数集合是 \(S\) 的答案贡献,\(S\) 用状压表示,但是需要记录每一个质数,这样就会爆掉,于是我们可以考虑用一个很重要的 trick:根号分治。
对于 \(\le \sqrt v\) 我们用状压,\(>\sqrt v\) 的由于每个 \(a_i\) 至多只有一个这样的质因子,我们可以把它领出来考虑。具体来说,对于每个 \(>\sqrt v\) 的质数开一个二元vector,存的是包含它的 \(a_i\) 还有 \(a_i\) 的小质数状压集合。记 \(f_{i,S,0/1}\) 表示对于前 \(i\) 个数,当前选的小质数集合是 \(S\),有没有选第 \(i\) 个数对应的大质数(如果没有大质数这个就不用管),可以把第一维压掉,把对应大质数相同的放在一起转移,注意由于大质数贡献只能有一次,这相当于是一个 01 背包,把第一维压掉后要倒序枚举转移。时间复杂度 \(O(n2^V+V2^V),V=16\)。
启发:
- 数论相关的还是要去熟悉基本计算式和一些性质。
- 根号分治在质数的应用太经典了,运用了 \(>\sqrt n\) 的质因数最多 1 个的重要性质。
课件知识点不太了解的
-
莫队二次离线。
-
操作树,可撤销并查集+分块。
-
惰性堆。
-
树分块。
trick 整合
题目
P2824 [HEOI2016/TJOI2016] 排序 \(\checkmark\)
题目大意
给定一个 \(1\sim n\) 的排列,进行 \(m\) 次操作:
0 l r:将下标区间 \([l,r]\) 内的数升序排序;1 l r:将下标区间 \([l,r]\) 内的数降序排序。
所有操作结束后,询问第 \(q\) 个位置上的数字。\(n,m\le 10^5\),\(1\le q\le n\)。
解题思路
我们只需要查询一个位置,这很好。
对于排序问题我们都可以考虑转 01,二分 mid,做一遍 \(m\) 次操作,只需要用线段树模拟,支持区间修改成 0 或者 1,区间查询 1 的个数,最后看看第 \(q\) 位是不是 0/1,继续二分。时间复杂度 \(O(m\log n)\)。
启发:
- 对于排序问题,很多时候我们都可以转成 01 来考虑,研究排序的本质就是把 0 前移,1 后移。
P6619 [省选联考 2020 A/B 卷] 冰火战士 \(\checkmark\)
题目大意
有冰、火两派战士,每个战士有温度 \(x\) 和能量 \(y\)。给定场地温度 \(T\) 时:
- 冰系战士可参赛当且仅当 \(T\ge x\);
- 火系战士可参赛当且仅当 \(T\le x\)。
双方可参赛战士按题述顺序依次对战,双方每轮消耗相同能量。若冰系可参赛总能量为 \(I(T)\),火系可参赛总能量为 \(F(T)\),则总消耗为
求使总消耗最大的最高温度 \(T\),并输出该温度及最大总消耗;若不存在使双方都有战士可参赛的温度,输出 Peace。
动态维护:共 \(Q\) 次操作,每次加入一个战士(给出派系 \(t\)、温度 \(x\)、能量 \(y\))或撤回之前某条加入操作,要求在每次操作后立即输出当前答案。
\(1\le Q\le 2\times 10^6\),\(1\le x\le 2\times 10^9\),所有 \(y\) 之和不超过 \(2\times 10^9\)。
解题思路
简单转化后的题意如上,肯定可以离散化。仔细读一读,相当于我们需要动维护一个单调的离散函数,\(f\) 单调不降,另外 \(g\) 单调不增,我们需要求出一个离散位置使得两个函数值的 \(min\) 最大,在 \(min\) 最大情况下位置下标也最大。
其实本质是求两条函数 \(f,g\) 的交点,但是这是离散的。所以我们就变成了求最大的 \(f(x)\le g(x)\) 的 \(x\),以及最前的 \(f(x)>g(x)\)(这个前一个 \(x+1\) 即可),注意,这里如果存在 \(x'>x\) 且 \(g(x')=g(x)\),那么取 \(x'\)。
动态来做的话就需要上数据结构,一方面支持后缀前缀修改,一方面也要支持二分(如果要单 \(\log\)),我们肯定可以用线段树来做,但是如果你想要更优常数(这道题卡)也可以用树状数组,难点在于树状数组上的倍增。
实现上前后缀修改其实可以统一,其中一个最后用总结果减一减算一算就行了。
启发:
- 当成树状数组练手题。
CF1762F Good Pairs \(\checkmark\)
题目大意
给定长度为 \(n\) 的数组 \(a\) 和整数 \(k\)。若存在下标序列 \(i_1,i_2,\dots,i_m\),满足:
- \(i_1=l\),\(i_m=r\);
- \(i_1<i_2<\cdots<i_m\);
- 对每个 \(1\le j<m\),都有 \(\lvert a_{i_j}-a_{i_{j+1}}\rvert\le k\),
则称点对 \((l,r)\) 是“好对”。求满足 \(1\le l\le r\le n\) 的“好对”数量。
多组数据,\(1\le t\le 10^5\),\(1\le n\le 5\cdot10^5\),\(0\le k\le 10^5\),\(1\le a_i\le 10^5\),且所有数据中 \(n\) 之和不超过 \(5\cdot10^5\)。
解题思路
首先考虑判定一个区间 \([l,r]\) 是不是好的,我们发现,对于好的序列,它一定是单调的,因为如果存在 \(x\to y\to z\) 且满足 \(a_x>a_y<a_z\) 或者 \(a_x<a_y>a_z\),那么 \(x\to z\) 也是合法的,所以一段合法序列肯定等价于一个单调的序列。
注意也有可能是 \(a_x=a_y\),它们也能到,所以这个可以提前算出,最后容斥掉。
单调不增和单调不降是对称的,所以我们这里统一考虑单调不降。
我们倒着处理,对于 \(i\),找到最小的 \(j\) 满足 \(a_j\in (a_i,a_i+k]\),定义其为 \(nxt_i\),容易发现定义 \(f_i\) 为以 \(i\) 为左端点的好区间个数,那么在这里 \(f_i\gets f_{nxt_i}\),但是还有一些位于 \((a_i,a_{nxt_i})\) 之间的数是 \(i\) 到的了的,\(nxt_i\) 到不了的。
综上所述,我们需要找到 \(nxt_i\),统计 \([a_i,a_{nxt_i}]\) 的数的个数,所以用一颗权值线段树足够了,并且值域数据范围是小于 \(n\) 的,所以能过。
统计单调上升的就是把序列翻转一下就行了。
P9060 [Ynoi2002] Goedel Machine \(\checkmark\)
题目大意
给定长度为 \(n\) 的序列 \(a_1,\dots,a_n\)。有 \(m\) 次询问,每次给出区间 \([l_i,r_i]\),求
即该区间内所有非空子集的最大公约数之积,对 \(998244353\) 取模。
\(1\le n,m,a_i\le 10^5\),\(1\le l_i\le r_i\le n\)。
解题思路
对于这种公约数题目,我们都可以拆成与枚举质数有关的东西,这是比较典的拆贡献方法。
比如说,经典的,我们枚举每个质数 \(p\),数一数当前询问区间有多少个数是满足 \(p\mid a_i\),假设当前个数为 \(c\),那么这个质数的贡献是 \(p^{2^c-1}\)。进一步,我们发现其实可以枚举 \(p^k\),每次就相当于在 \(p^{k-1}\) 的基础上增量而已。
分析复杂度,我们的质数幂次个数是大于质数个数的,但是比较接近,可以自己写份代码验证一下。因为质数个数是 \(O({n\over \ln n})\) 级别的,所以这样做的复杂度肯定会炸掉。
我们尝试套上经典 trick,根号分治,记 \(w=\max a_i\),将 \(p\) 分成 \(\le \sqrt w\) 和 \(>\sqrt w\) 的。
对于 \(p\le \sqrt w\),我们直接用上面的思路,预处理出 2 的幂次还有逆元,这样的复杂度是不会超过 \(O(m\sqrt w+m\sqrt w)\)。
对于 \(p>\sqrt w\),每个 \(a_i\) 至多只有一个这样的 \(p\),所以我们可以用莫队,每次移动左右端点都只会使区间内的 \(p\) +1,-1,所以这一部分也用上预处理之后的时间复杂度是 \(O(n\sqrt m)\)。
预处理最好不是 \(2^k\) 此方的,这个后面还是比较麻烦,可以直接预处理 \(p^{2^k}\),最后在 \(\times p^{-1}\) 即可。
\(n,m,w\) 同阶,总时间复杂度就是 \(O(n\sqrt n)\)。
启发:
-
对于这种公约数题目,我们都可以拆成与枚举质数有关的东西,这是比较典的拆贡献方法。
-
根号分治对于质数的运用。
CF809E Surprise me!
题目大意
给定一棵 \(n\) 个点的树,点 \(i\) 权值为 \(1\sim n\) 的排列 \(a_i\)。等概率随机选有序点对 \((u,v)\),\(u\ne v\),求
的期望。设该期望为最简分数 \(\frac{P}{Q}\),输出 \(P Q^{-1}\bmod 10^9+7\)。其中 \(\varphi\) 为欧拉函数,\(d(u,v)\) 为树上距离。\(2\le n\le 2\cdot 10^5\)。
解题思路
法一:
考虑 \(\varphi(a_u,a_v)={\varphi(a_u)\varphi(a_v)d\over \varphi(d)}\),等价形式:\(\varphi(a_u)\varphi(a_v)\prod_{p|a_u,a_v} {p\over p-1}=\varphi(a_u)\varphi(a_v)\prod_{p|a_u,a_v} (1+{1\over p-1})\) 后面那一坨可以用组合意义展开成
其中 \(S\) 表示的就是 \(p\mid a_u,a_v\) 所有 \(p\)的集合,然后 \(T\) 是枚举的。我们可以把后面的 \(\prod\) 看成一个积性函数,也就是我们令 \(x=\prod_{p\in T}\),令 \(g(x)=\prod {1\over p-1}\)。整理一下变成 \(\sum_{x|a_u,a_v} g(x)\)。由于我们前面要求的 \(T\) 是一个集合,所以 \(g(x)\) 应该也是要类似集合那种互异性,也就是不能存在 \(p^2\) 或以上的因子。故 \(g(x)\) 在此种情况中也就是 \(\mu(x)=0\) 的时候 \(g(x)=0\),其余遵循上面的合并式子,这个是可以用线性筛预处理。
原本的式子再交换一下求和顺序变成了
枚举 \(x\),现在的问题是处理后面的,令 \(c_u=\varphi(a_u)\),后面的东西可以摊到一条边上,算一算这条边子树内 \(c\) 的和,还有子树外的和,两个乘起来即可。
现在直接做这个问题还是 \(O(n^2)\) 的,但是我们注意到题目给出的 \(a\) 是一个排列,也就是对于每个 \(x\),合法的 \(x|a_u\) 并不会很多,总的量级是 \(O(n\ln n)\)。
然后我们每次将这些点拿出来,建立虚树,简单树形 DP 即可。
实现上我们对于每次建立虚树如果都要 \(O(siz \log siz)\) 排序的话复杂度可能会受不了,虽然也能过。但是可以进一步优化,很经典的问题,如果每次内部都要排序,但是排序规则都是一样的,我们可以在外部先排一次序,然后直接从中按顺序取出边可以省掉内部排序的 \(\log\)。
代码还没写,一定要补,好题。
启发
-
\(\sum\prod\) 似乎有非常经典的组合意义,他有一个对称的,比如说:
\(\sum_{T\subseteq S}\prod_{x\in T} x=\prod_{x\in S}(1+x)\),这个用组合意义很好理解,其实就是一个类似二项式的东西,好像 ZRC Day 29 有类似的题。 -
如果对于一坨式子不好处理的,可以将其成为一个函数,然后就能好做很多。
-
很经典的问题,如果每次内部都要排序,但是排序规则都是一样的,我们可以在外部先排一次序,然后直接从中按顺序取出边可以省掉内部排序的 \(\log\)。

浙公网安备 33010602011771号