数论 | 同余代数

部分内容从 Alex_Wei 博客学习整理并截取。

基本概念/符号

\(\alpha ~ \beta~ \delta~ \epsilon~ \eta~ \gamma~ \mu~ \varphi \bot \pm\)
剩余类:模 \(n\) 同余的所有数构成的等价类被称为模 \(n\) 的剩余类。当我们在模
\(n\) 意义下讨论它们时它们等价。模 \(n\)\(i\) 的剩余类记作 \(K_i\)。显然模 $ n$ 的剩余类共 \(n\) 个。
完全剩余系:从模 \(n\)\(n\) 个剩余类中各选择一个数,它们构成模 \(n\) 的完全剩余系。
简化剩余系:从与 \(n\) 互质的剩余类中选择各选择一个数。

质数

埃氏筛

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

对于较大值域 \([L,R]\),但是范围 \(R-L+1\) 很小的质数寻找可以通过处理 \(\sqrt R\) 之内的所有质数,然后往上标记 \(i\times p\),其中 \(i\in [\lceil\dfrac{L}{p}\rceil,\lfloor\dfrac{R}{i}\rfloor]\)。同时这个过程不需要 map 来标记,可以通过平移 \(L\) 来平移到数组可接受范围。
应用:Prime Distance

线性筛

每个数只被最小的质因子标记,时间复杂度 \(O(n)\)

流程: 记录 \(v_i\) 表示 \(i\) 最小的质因子。从小到大扫描,如果遇到一个数没有被标记,就把它标记为质数,\(v_i\gets i\)

对于扫描到的每个数 \(i\),我们可以从小到大枚举目前已经找到的质数 \(p_j\),如果 \(p_j \le v_i\),那么 \(v_{p_j\times i}\gets p_j\),否则就退出。

P10495 阶乘分解

对于质数 \(p\),其出现次数为 \(\sum\limits_{k}^{p^k\le n}\lfloor\dfrac{n}{p^k}\rfloor\)

\([1,n]\) 中的质数出现次数是 \(O(\dfrac{n}{\log n})\) 的,处理上述式子的复杂度是 \(O(\log n)\) 的,所以乘在一起整个算法其实是线性的。

Miller-Rabin

利用费马素性检测 \(+\) 二次探测定理判断 \(p\) 是否为质数。

逆运用费马小定理,找一些 \(a\),看看是否满足 \(a^{p-1}\equiv 1 \pmod p\)

  • \(561\) 是上述算法一个很好的反例。

于是需要二次探测定理。

根据二次剩余,当 \(p\) 为奇质数的时候,\(x^2\equiv 1\pmod p\) 有且仅有解 \(\pm 1\)。因此如果有 \(x\neq\pm 1\) 满足 \(x^2\equiv 1\pmod p\),那么 \(p\) 也就不是奇质数了。

上述当满足第一条限制的时候,我们已经找到了 \(a^{p-1}\equiv 1\pmod p\),如果当前指数为偶数,我们考虑对其不断开根号,看看是否满足上述要求,同时如果遇到 \(-1\) 就结束,如果遇到了 \(1\) 就继续开根,直到无法继续开根或者遇到 \(-1\) 就结束了。当然我们肯定无法直接开根,是用快速幂乘上来的。所以这会多一个 \(\log\) 的复杂度。

考虑从下往上做,这样子只需要平方就行了。设 \(k\) 为选择的 \(a\) 的个数,时间复杂度 \(O(k\log n)\)

质因数分解

朴素分解是 \(O(\sqrt n)\) 的。

如果是多组且值域小的话,可以线性筛,筛出值域内每个数的最小质因数,然后单次 \(O(\log n)\) 求解。

约数

根据成对出现的性质暴力做是 \(O(\sqrt n)\) 的。

如果要处理多组,也可以预处理 \(O(\sqrt {2n})\) 范围内的质数,然后暴搜来确定约数。

void dfs(int cnt,ll mul,int num){
	if(cnt>tot){
		if(mul!=1) fc[++m]=mul;
		return ;
	}
	for(int i=0;i<=c[cnt];i++) 
        dfs(cnt+1,mul),mul*=d[cnt];
}

P1463 [POI2001] [HAOI2007] 反素数

很基本的观察就是只会用到前面的若干个很少的质数,以及指数很小。

然后就是本题最关键的一点了,这是一个很重要的对于指数的观察和调整法。质数上的指数随着质数的增大而减小,否则可以用替换法证明更优。直接搜索即可。

GCD/LCM

ZROI2998.朔望(多个数的 lcm)

认真分析题意,本题即求 \(\dfrac{\operatorname{lcm}(a_1,a_2..a_n)}{2}\bmod 998244353\)
就是如果不考虑爆 long long 的问题话,可以设 \(l_i=\operatorname{lcm(a_1,...a_i)}\),每次 \(l_{i+1}=\operatorname{lcm(a_{i+1},l_i)}=\dfrac{a_{i+1}\times l_{i}}{\gcd(a_{i+1},l_i)}\),最后算出来的 \(l_n\) 就是答案了,这显然是正确的。

计算 \(\operatorname{lcm}\) 的过程中显然无法直接对于 \(998244353\) 取模。直接算又会爆掉,所以我们考虑将 \(l_i\) 拆分,\(l_i=\prod\limits_{j=1}^ib_j\)。不直接维护 \(l\),而是通过 \(b\) 的乘积间接维护 \(l\)。于是有,

\(\begin{aligned}b_{i+1}&=\dfrac{l_{i+1}}{l_i}\\ &=\dfrac{a_{i+1}\times l_{i}}{\gcd(a_{i+1},l_i)\times l_i}\\ &=\dfrac{a_{i+1}}{\gcd(a_{i+1},l_i)}\\ &=\dfrac{a_{i+1}}{\gcd(a_{i+1},\prod\limits_{j=1}^i b_j)} \end{aligned}\)

可以如果直接计算 \(\prod\limits_{j=1}^ib_j\) 还是会爆 long long,注意到

\[\gcd(a_{i+1},\prod\limits_{j=1}^ib_j)=\gcd(a_{i+1},\prod\limits_{j=1}^ib_j\bmod a_{i+1}) \]

小心这里要用到 64 位整数乘法。

于是直接枚举 \(1\)\(n\),计算 \(b_i\)。最后答案就是 \(l_n=\prod\limits_{i=1}^n b_i。\)对于每个 \(i\),我们需要 \(O(n)\) 计算 \(b\) 的前缀积对于 \(a_i\) 的取模,于是时间复杂度就是 \(O(n^2)\) 的。

P1072 [NOIP2009 提高组] Hankson 的趣味题

应该从 "集合" 的角度来理解,\(\gcd\) 是交集,\(\operatorname{lcm}\) 是并集。

先将大的约束限制放到每个质因子的指数上考虑,\(\gcd\) 要求取 \(\min\)\(\operatorname{lcm}\) 要求取 \(\max\),分类讨论,组合计数算一下即可。

同余基础知识

费马小定理

\(p\) 为质数且 \(a\) 不是 \(p\) 的倍数时候,满足 \(a^{p-1}\equiv 1(\bmod p)\)

乘法逆元

  1. \(a\)\(p\) 互质的时候,存在乘法逆元。
  2. \(p\) 为质数的时候,\(a^{-1} \equiv a^{p-2} (\bmod p)\)
  3. 线性求逆元:记 \(i\) 的逆元为 \(inv_i\)。设 \(p=k\times i+r(0 \le r<i)\),于是有 \(ki+r \equiv 0 (\bmod p)\),两边同时除以 \(ir\),得到 \(i^{-1} \equiv-kr^{-1} (\bmod p)\),代入 \(k=\lfloor\frac{p}{i}\rfloor\),以及之前已求出的 \(r\) 的逆元即可。
  4. 线性求任意 \(n\) 个数的逆元,设 \(mul_i\)\(a_i\) 前缀积,先算出 \(mul_n^{-1}\),然后利用 \(mul_i^{-1}=mul_{i+1}^{-1} \times a_{i+1}\),算出 \(mul_i^{-1}\) 各项的值。最后通过 \(a_i^{-1}=mul_{i-1} \times mul_i^{-1}\) 就可以求出 \(a_i\) 的逆元了。

威尔逊定理

由于乘法逆元是相互的,所以考虑乘法逆元的配对。

自己和自己逆元的情况,只有 \(x^2\equiv 1\pmod p\) 的时候才会出现,也就是 \(1\)\(p-1\),剩下的 \(2\sim p\) 都能两两匹配。所以可以得到 \((p-1)!\equiv -1 \pmod p\) 当且仅当 \(p\) 是质数。

当然我对于充分性的证明不感兴趣。

扩展形式

\((p^k!)_p\) 表示 \(p^k\) 以内与 \(p\) 互质的数的乘积模 \(p^k\),其中 \(p\) 为素数。

\((p^k!)_p=\begin{cases}1&p=2 \wedge k\ge 3 \\-1& \operatorname{otherwise} \end{cases}\)

素数在阶乘中的幂次(Kummer 定理)

\(v_p(n!)=\dfrac{n-s_p(n)}{p-1}\)

其中 \(s_p(n)\) 表示 \(n\)\(p\) 进制下各位和。

利用这个公式也可以推出素数在组合数中的幂次。

裴蜀定理

\(a,b\) 互质的充分必要条件为存在 \(x,y\) 使得 \(ax+by=1\) 成立。

P4549 【模板】裴蜀定理

裴蜀定理的推论是 \(\sum x_ia_i\) 能表示的数为 \(\gcd(a_1,a_2,..a_n)\) 的倍数。

CF1515G Phoenix and Odometers

很牛的一道数论和图论相结合的题目。

注意到由于要求走出一条回路,所以我们必须在 \(u\) 所在强连通分量中走,而且还必须是若干个环的组合,否则无法回到起点。由于是若干个环的线性组合,所以也可以看出一个强连通分量中作为起点的答案是相同的。

于是设强连通分量中有 \(m\) 个环,环长为 \(l_i\)

那么就是要求 \(\sum l_ix_i\equiv t-s \pmod t\)

根据裴蜀定理,一个强连通分量内的环可以表示出来的数必须满足是 \(\gcd(l_1,l_2..l_n,t)\) 的倍数。

对于一个强连通分量中可能有很多很多环的存在(存在一堆环合并的情况),但是我们其实只要求出简单环即可,也就是 dfs 树上一条非树边连出的环即可。因为就是有多个环合并成大环,最后的本质也都是小环的线性组合,肯定满足 \(\gcd(l_1,l_2,..,l_z)=\gcd(l_1,l_2,..,l_z,\sum x_il_i)\)

于是对于每个强连通分量求出 \(\gcd\) 即可。

时间复杂度 \(O((n+q)\log V)\)

P3518 [POI2011] SEJ-Strongbox

noip 考前复习数论,希望别考。

从限制入手,最后密码的线性组合不能表示出 \(m_i,i\in [1,k-1]\)。假设最后的密码序列为 \(\{a_i\}\),那么必须满足 \(\sum x_ia_i\bmod n \neq m_j,j\in [1,k-1]\)

这个取模可以很经典地转化成 \(\sum x_ia_i+x n\),也就是 \(a_1,a_2,..,n\) 的线性组合,利用裴蜀定理可以转化为 \(d=\gcd(a_1,a_2...n)\) 的倍数中 \(<n\) 的数。

考虑枚举 \(d\),由于我们已经知道了 \(a_i\) 中的一个数为 \(m_k\),故 \(d\mid \gcd(m_k,n)\)。考虑枚举符合要求的 \(d\),然后只需要满足 \(d\nmid m_i,i\in[1,k-1]\) 即可。

暴力做的话,时间复杂度为 \(O(d(n)k)\),会超时。

考虑反向求出所有不能被用的数,不过如果枚举 \(m_i\),再枚举其因数用 map 保存肯定还是不太行。

不过可以发现上述过程干了很多没有用的事情,可能作为答案的数只有 \(d(\gcd(m_k,n))\) 个,而我们预处理不合法的数却足足标记了 \(\sum\limits_{i=1}^{k-1}d(m_i)\) 个数,很多都是无用的数!

于是我们只需要在 \(\gcd(m_k,n)\) 的因数集内做标记不合法的数即可。从大到小枚举因数集中的数,如果遇到了 \(m_i\),首先将这个数标记不合法,其次 \(m_i\) 的约数集和 \(\gcd(m_k,n)\) 约数集的交集中的数要标记不合法,暴力枚举还是不合适。考虑 "不合法标记下传",由于我们是从大到小枚举,所以我们可以将不合法的标记往下传递给最大的几个数,使得这几个数是其他并集中数的倍数,这样子等枚举到他们的时候标记可以继续下传至所有数。我们可以把标记传给 \(\dfrac{m_i}{p_j}\),其中 \(p_j\)\(n\) 的质因子。这样子,我们就只会标记 \(d(\gcd(m_k,n))\) 个数,时间复杂度就正确了。

在得到符合所有要求的最小 \(d\) 之后,最后的答案即为 \(\dfrac{n-1}{d}\) 吗?其实别忘记考虑 \(0\),可以发现 \(0\) 不可能作为不合法密码,因为 \(xd_k\bmod n\) 必然可以取到 \(0\),如果 \(0\) 是不合法密码的话就矛盾了,所以本题答案就是 \(\dfrac{n-1}{d}+1=\dfrac{n}{d}\)\(d\mid n\))。

时间复杂度 \(O(\sqrt n+(k+d(n)w(n))\log n)\)

QOJ10043.Mod Graph

发现这个条件很神秘。直接行走的话影响到的点太多了。

故考虑一些特殊的行走,发现从 \(x\) 点开始不断走 \(x\to y\)\(y\to x\),直到走了 \(\rm lcm (b_x,b_y)\) 轮且最后停在了 \(y\),那么 \(y\) 的权值不变,\(x\) 的相当于减少了 \(1\)。同时进入一个点的时候可以让它的权值 \(+1\),所以考虑一个 \(x\to y\to z\) 的链,我们可以先走 \(x\to y\),再在 \((y,z)\) 之间进行上述的反复横跳,最后停在 \(z\),就可以实现无代价从 \(x\)\(z\)。这样子所有图上距离为偶数的点都可以无代价互达,所以图上存在奇环的时候,可以走一次奇环改变距离奇偶性,这样子就达成了全图任意走。

于是当图上有奇环的时候,答案就必定是 YES。因为我们有“只修改当前所在点 \(-1\) 的操作”而且不会影响别的点,我们就不断执行:让这个点 \(-1\),然后在图上无代价行走走回去,继续对这个点操作,直到其权值为正确的。

但是当图没有奇环的时候(等价于图是二分图),每次行走之后就从左部到达了右部,或者从右部到了左部,想再走回去,由于没有奇环,就需要再执行一次 \(+1\) 或者 \(-1\) 操作才能回去。所以我们只能在左边内部任意行走,右边内部任意行走,左右跨过去需要 \(1\) 的代价。

所以我们先操作掉左右的 \(\sum b_i-a_i\),这个时候因为两边是交替 \(\pm 1\) 的,所以 \(\sum b_i-a_i\) 应该至多差为 \(1\),如果不是的话我们可以用左右的 \(b_i\) 来凑,是一个 \(\sum k_ib_i\) 的形式,可以直接用裴蜀定理处理,也就是说我们提前对于所有 \(b_i\)\(\gcd\),最后判断都是在模 \(\gcd(b_1,b_2\dots b_n)\) 的情况下判断的。

环上固定步长行走

在一个长度为 \(n\) 的环上,不断行走,每次走 \(k\) 步,最后会形成一个长度为 \(\dfrac{n}{\gcd(n,k)}\) 的子环。如果改变起点,一共有 \(\gcd(n,k)\) 种这样子的子环。(如果忘记,就令 \(k=1\) 来推)。

上述表达和这个结论很有关联:在 \(a\bot b\) 的情况下,\(ax\bmod p\) 取遍 \([0,p-1]\)

杂题

P7325 [WC2021] 斐波那契

前置知识:同余式的除法

对于 \(a\equiv b\pmod p\) 的同余式,当 \(a\bot p\) 的时候可以直接使用乘法逆元。但是不互质的时候,乘法逆元不成立,更一般的情况是,我们可以同时除以 \(\gcd(a,p)\),注意 \(a,b,p\) 都要除以这个数。根据同余的性质有 \(\gcd(a,p)=\gcd(b,p)\)(辗转相除可证),所以 \(\gcd(a,p)\mid b\) 是必然存在的,且新的 \(a',b',p'\) 互质。

可以手动模拟观察一下,记题中序列为 \(G\)\(F_1=1,F_2=1\) 的斐波那契数列为 \(F\)。那么 \(G_n=aF_{n-1}+bF_n\)

这一步的好处在于,把原来前两项不固定的数列变成了一个固定的数列。原来题目中会给出 \(n\) 个数列,很难在 \(\log\) 或者 \(\sqrt n\) 的时间内处理。而现在我们只需要处理 \(1\) 个数列了,有结论:斐波那契数列在模 \(m\) 的意义下有 \(O(m)\) 的循环节。

那么 \(G_n\equiv 0\pmod m\),就等价于 \(aF_{n-1}\equiv -bF_{n}\pmod m\)

\(b\to -b\),可以得到 \(aF_{n-1}\equiv bF_{n}\pmod m\)。如果此时 \(m\) 是质数的话,直接预处理 \(\dfrac{F_n}{F_{n-1}}\) 的逆元即可。

本题中由于 \(m\) 不一定是质数,所以可以运用同余式除法的知识。先对于 \(a,b,m\) 统一处理一下。在同余式两边同时除以 \(d=\gcd(a,b,m)\),那么就转化为 $$\frac{a}{d}F_{n-1}\equiv\frac{b}{d}F_n\pmod{\frac{m}{d}}$$

这个时候要小心,之前是单纯 \(a\equiv b\pmod m\) 的情况,所以有 \(\gcd(a,p)=\gcd(b,p)\),保证除过之后就互质了,现在多了 \(F\) 这一项就不满足了。因此令 \(d'=\gcd(\frac{b}{d},\frac{m}{d})\),再做一次除法。

根据斐波那契数列的性质,\(\gcd(F_n,F_{n-1})=1\),可以得到 \(d'\mid F_{n-1}\)。所以再次都除以 \(d'\)\(\dfrac{b}{dd'}\)\(\dfrac{m}{dd'}\) 互质。故 $$\dfrac{a}{d}\dfrac{F_{n-1}}{d'}(\dfrac{b}{dd'})^{-1}\equiv F_n\pmod {\dfrac{m}{dd'}}$$

还是同样的方法,我们希望把 \(F_{n-1}\) 放过去。根据同余的性质,同余式左右两侧和模数的 \(\gcd\) 相等,可以进一步推得 \(\gcd(\dfrac{F_{n-1}}{d},\dfrac{m}{dd'})|F_n\),又因为 \(\gcd(F_{n-1},F_n)=1\),可以得到那个 \(\gcd\)\(1\)。所以互质情况下直接除过去就行了。

\[\dfrac{a}{d}(\dfrac{b}{dd'})^{-1}\equiv F_n(\dfrac{F_{n-1}}{d'})^{-1}\pmod{\dfrac{m}{dd'}} \]

对于给定 \(a,b,m\),我们可以求出 \(d,d'\),所以只需要提前保存三元组 \((d,d',F_n(\dfrac{F_{n-1}}{d'})^{-1}\pmod{\dfrac{m}{dd'}})\) 即可。

直接枚举所有三元组会爆,可以考虑先枚举 \(d\),然后 \(d'=\gcd(\dfrac{m}{d},F_{n-1})\),注意到这是与 \(\frac{m}{d}\) 有关的式子,所以我们只需要枚举对于模 \(\frac{m}{d}\) 意义下的 \(F\) 即可。复杂度是 \(m\) 的约数和,这个数字是 \(O(m\log\log m)\) 级别的。

所以总的时间复杂度就是 \(O(m\log\log m+n\log m)\)

扩展欧几里得算法

扩展欧几里得算法是用于求解形如 \(ax+by=c\) 的方程,根据裴蜀定理其有解的充要条件是 \(\gcd(a,b) | c\)

我们可以利用类似于求解 \(\gcd\) 的方法来算 exgcd。由于 \(\gcd(a,b)=\gcd(b,a\bmod b)\),所以把系数替换成 \((b,a\bmod b)\) 不仅保证有解,而且还缩小了问题规模,如果不断缩小问题规模直到边界条件就可以很轻松的得到一组解,而且根据辗转相除法,我们进行这个的轮数为 \(O(\log V)\)

我们现在计算 \(ax+by=d=\gcd(a,b)\)。假设我们已经知道了 \(bx'+(a\bmod b)y'=d\) 的解了,那么有

\(ax+by=bx'+(a\bmod b)y'=bx'+(a-\lfloor\dfrac{a}{b}\rfloor\times b)y'\)
也就是 \(ay'+b(x'-\lfloor\dfrac{a}{b}\rfloor y')\)

对比系数,\(x\gets y',y\gets x'-\lfloor\dfrac{a}{b}\rfloor y'\)

按照上述流程递归求解即可。

临界条件是最后 \(a=d,b=1\),此时解为 \(x=1,y=0\)

最后解出 \(ax+by=d\) 后,将解 \(\times\dfrac{c}{d}\),就可以得到一组特解 \((x_0,y_0)\) 了。

exgcd 求出来的特解是满足 \(ax+by=d\)\(\lvert x\rvert+\lvert y\rvert\) 最小的一组解,注意这里的必须是 \(=d\) 的解,如果是 \(=c\) 的话就不满足这个性质了! 关于如何在 \(=c\) 的时候求出这个最小解,可以去看看 P3543

有了特解之后,我们需要得到方程的特解。

\(x,y\) 的变化量为 \(\Delta x\)\(\Delta y\),有 \(a\Delta x+b\Delta y=0\)。得到 \(\Delta x=-\dfrac{b}{a}\Delta y=-\dfrac{b/d}{a/d}\Delta y\)(最后一步是约分)。

所以可以得到方程的通解为 \(\begin{cases} x=x_0+\dfrac{b}{d}k \\y=y_0-\dfrac{a}{d}k \end{cases}\)

得到通解的表达式之后就可以求一些特殊位置的解了。

P5656 【模板】二元一次不定方程 (exgcd)

\(A=\dfrac{a}{d},B=\dfrac{b}{d}\),根据通解表达式可以得到 \(x\equiv x_0\pmod B\),于是 \(x\) 的最小正整数解就是

\[\begin{cases} x_0\bmod B&x_0>0 \\x_0\bmod B+B& x_0<0 \end{cases}\]

对于 \(y\) 同理。

对于 \(x,y\) 都是正整数的情况下,显然是其中一个变大会让另一个变小,所以 \(x\) 的最小正整数解对应的是 \(x>0\) 的情况下 \(y\) 的最大值。注意特判掉此时 \(y\) 最大值 \(<0\) 的情况。

关于 \(x,y>0\) 的解的个数,由于 \(x\) 每次变化 \(B\),那么就是 \(\dfrac{x_{\max}-x_{\min}}{B}+1\) 了。

P3951 [NOIP 2017 提高组] 小凯的疑惑

由于题目说了 \(\gcd(a,b)=1\),所以根据裴蜀定理 \(ax+by\) 是可以表示所有正整数的。但是由于要求 \(x,y\) 非负,所以有一些数字是无法表示出来的,这些数字肯定有 \(x,y\) 中的至少一个 \(<0\)

要求这个数字尽可能大,所以两个都小于 \(0\) 肯定不优。

那么这个最大的不能被表示的数肯定有一个 \(x\) 或者 \(y <0\)(我们就假设 \(x>0,y<0\)),同时要求 \(ax+by\) 不能被另一组 \(ax'+by'\) 表示出来。假设能被另一组表示出来,需要满足 \(\dfrac{a}{b}=\dfrac{y'-y}{x-x'}\),并且要 \(x>0,y<0\),还有 \(x',y'\ge 0\)。要求上一个等式不成立,其实这个等式想要成立的话条件还是很宽松的,我们必须找到一个东西强制其不成立。

首先 \(a,b\) 互质,等式左边不可约分。如果我们强制分母的 \(x\le b-1\),由于 \(x'\ge 0\),所以分母肯定 \(<b\),也就肯定无法达成目标。同理在 \(y\le -(a+1)\) 的时候也是可以的。两者只需要满足一个。

在以上取值范围内,取 \(x=b-1,y=-1\) 的时候 \(ax+by\) 最大也就是 \(ab-a-b\)

ZROI2989. 波波牛一中

有两个人,一个人在连续 \(a\) 天中必须回班上至少一次文化课,另一个人则是 \(b\) 天。两个人不能同时回去,现在求 \(n\) 天中两个人回去上课天数之和最小。\(n\le 10^6\)

可以发现在 \(\operatorname{lcm}(a,b)\) 会相遇,我们必须要让一个提前一下。

具体是哪个,需要决策。注意到值域很小,我们可以 dp 一下,设 \(dp_{i,t}\) 表示还剩 \(i\) 天的时候,一个人在第 \(i\) 天,另一个人在第 \(i+1\) 天,具体是哪个人提前用 \(t\) 来表示。注意这个状态表示只能代表冲突天,所以我们第一次需要算 \(\operatorname{lcm}\),然后手动跳到第一个冲突天。

假设是 \(a\) 提前了,那么下一次相遇的位置就是 \(ax=by+1\),这个可以通过扩欧解一下方程。得到通解后,\(x\gets (x\bmod b +b)\bmod b\) 就可以得到 \(x\) 的最小正整数解了。然后我们跳到这一天继续 dp 即可。采用记忆化搜索实现。

如果无解或者会跳出去,那么就直接统计当前答案即可。

P1082 [NOIP2012 提高组] 同余方程

其实也就是求 \(a\) 在模 \(b\) 意义下的逆元。

\(ax\equiv 1 \bmod b \to ax+by=1\)。 exgcd 可解。

本题最大的应用就是求模数为非质数情况下的乘法逆元。

扩展一下,其实对于 \(ax\equiv b\pmod p\) 都可以转化为 \(ax+py= b\)

P3543 [POI2012] WYR-Leveling Ground

数论和贪心结合,好题!

区间加减是难做的,于是可以转化为差分数组 \(d_i=h_i-h_{i+1}\),其中 \(d_n=-h_n\)。然后我们对于 \(h\) 的区间加减就变成了对于 \(d\) 数组的两个单点操作一个 \(+\),另一个 \(-\)。我们需要把所有 \(d_i\) 都变成 \(0\),其中前 \(n-1\)\(d_i\) 变成 \(0\) 代表所有 \(h_i\) 都相等,最后一个 \(d_n\) 变成 \(0\) 代表 \(h_n\) 变成了 \(0\)。所以此时 \(h_1=h_2=\dots =h_n=0\)

对于每个点如果想把它操作为 \(0\),就是要求 \(ax_i+by_i=d_i\),其中 $\lvert x_i\rvert,\lvert y_i\rvert $ 分别表示 \(i\) 点两种操作的次数。因为一次操作是两个单点分别加减,所以必须满足 \(\sum x_i=0,\sum y_i=0\)

因为差分和 \(\sum d_i=0\),我们把所有等式累加得到 \(a\sum x_i+b\sum y_i=\sum d_i=0\),所以如果满足了第一条限制,就必然会满足第二条。我们要做的就是在满足限制的情况下求出 \(\min\{\dfrac{\sum\limits_{i=1}^n\lvert x_i\rvert +\lvert y_i\rvert}{2}\}\)其实如果直接去构造满足限制,会很难求解最小值。我们考虑求出最小值之后再不断调整使其满足限制。

先对于每个 \(i\),求出 \(ax_i+by_i=d_i\) 的最小 \(\lvert x_i\rvert +\lvert y_i\rvert\) 解。用 exgcd 解出方程的一个特解 \((x_0,y_0)\) 之后(如果某个方程无解,那么整个问题也是无解),我们可以得到通解的表达式 \(\begin{cases} x=x_0+\dfrac{b}{d}k \\y=y_0-\dfrac{a}{d}k \end{cases}\)

下面为了探讨问题方便,我们直接令 \(A=\dfrac{a}{d},B=\dfrac{b}{d}\)

  • 注意我们之前可能听说过 exgcd 求出的方程特解是满足绝对值之和最小的解,但是这个只是在 \(ax+by=\gcd(a,b)\) 才满足时候,如果等式右边为 \(c\),最后解 \(\times \dfrac{c}{\gcd(a,b)}\) 就会不满足了。

最小化 \(|x|+|y|\),即最小化 \(f(k)=\lvert x_0+kB\rvert+\lvert y_0-kA\rvert\)。可以发现 \(A,B\) 中必然有一个更大的,越大的数乘上系数 \(k\) 之后变化越大。不妨设 \(A<B\),所以我们考虑让 \(x_0+kB\)\(0\) 变化,\(\lvert y_0-kA\rvert\) 的肯定会增大但是幅度没有另一个减小得大。故当 \(A<B\) 的时候在 \(x_0+kB\) 取最小非负解或者最大负解的时候表达式取最小值。 对于 \(A>B\) 的情况同理。

找到最小解之后,为了满足约束条件。我们就要进行调整,使得 \(\sum x_i=0\)

我们可以每次选取调整代价最小的 \((x_i,y_i)\) 出来不断调整,可以发现在 \((x_i,y_i)\) 的符号不变的情况下,调整代价也是不变的,也就是 \(\lvert A-B\rvert\)。只有在某个符号突变的时候发生变化,于是我们可以用堆来维护调整代价最小的位置,然后每次取出后不断调整至符号将要突变,此时代价可能发生变化,我们不能保证最优,于是需要放回堆中重新决策。由于符号只会变 \(O(1)\) 次,所以每个点进出堆的次数也是 \(O(1)\) 的,不断调整直至 \(\sum x_i=0\),时间复杂度 \(O(n\log n)\)

不过还有一个观察是(以最小非负整数为例)我们在寻找 \(x_i\) 的时候是 \((x_i\bmod B+B)\bmod B\),所以 \(x_i<B\),故 \(\dfrac{\sum x_i}{B}\) 是在 \(O(n)\) 级别的。我们每次调整一次就放回堆中也就是复杂度正确的。

CF1728E Red-Black Pepper

\(w_i\) 表示使用了 \(i\) 个红辣椒的方案数,可以通过简单贪心求得。

重点就是发现 \(w_i\) 是一个单峰函数,然后就简单了,用 exgcd 求出通解之后,让其尽可能接近峰,也就是同余意义下的点定位。

中国剩余定理

CRT

用于求解若干个形如 \(x\equiv a_x \pmod {m_i}\),其中 \(m_i\) 两两互质。

我们给出以下构造,\(M=\prod m_i\),那么最后 \(x=\sum\limits_{i=1}^na_i\dfrac{M}{m_i}(\dfrac{M}{m_i})^{-1}\)

首先,\(\dfrac{M}{m_i}\) 的作用是使得某个式子在除了 \(i\) 之外的同余式上这一项都取 \(0\)\(a_i\) 的目的是为了满足同余式,可是对于 \(i\) 来说其同余式多了一个 \(\dfrac{M}{m_i}\),直接乘以模 \(m_i\) 意义下的逆元 \((\dfrac{M}{m_i})^{-1}\),即可消掉这一项。这个逆元需要用 \(\rm exgcd\) 求解,也就是 \(x\dfrac{M}{m_i}+ym_i=1\)。同时注意到如果 \(\dfrac{M}{m_i}\)\(m_i\) 不互质,不定方程无解,这也就是为什么 CRT 要求 \(m_i\) 两两互质。

ExCRT

用于求解模数不互质的情况。

考虑合并方程来求解,目前有两个方程 \(x\equiv a_1\pmod {m_1}\)\(x\equiv a_2\pmod {m_2}\)。不妨对于第一个方程设 \(x=pm_1+a_1\),带入第二个方程中,\(pm_1+a_1\equiv a_2\pmod {m_2}\),解一下 \(p=\dfrac{a_2-a_1}{m_1}\pmod {m_2}\),可以用 exgcd 来求解。合并之后的方程就是 \(x\equiv a_1+pm_1\pmod {\operatorname{lcm}(m_1,m_2)}\)。求逆元那一步可能不存在,就意味着在 \(\gcd(m_1,m_2)\nmid a_2-a_1\) 的时候,不存在解了。

P4621 [COCI 2012/2013 #6] BAKTERIJE

直接搜出每个细菌从四种方向进入陷阱的周期。然后暴力枚举每种细菌是从哪个方向进入的。

使用 ExCRT 合并周期,算出最后的时间即可。注意我们的时间是形如 \(kT+d\) 的形式,但是可能 \(d>T\)(第一次进入时间大于周期),这个时候直接用同余方程 \(x\equiv d\pmod T\) 的话可能得到 \(<d\) 的解。我们需要对于最后得到的解,进行 \(\ge d\) 的约束检测,如果不满足这个约束就加上若干倍的周期使得其 \(\ge d\)

P12828 「DLESS-2」XOR and Number Theory

不妨设 \(y\ge x\),首先有不等式 \(x\oplus y\ge y-x\),还有 \(\gcd(x,y)=\gcd(x,y-x)\le y-x\),所以当 \(x\oplus y=\gcd(x,y)\) 的时候,可以得到这个值为 \(y-x\)

以上两个式子的取等条件分别为 \(x\subset y\)\(y-x\mid x\),第二个条件可以得到 \(ky=(k+1)x\)。利用这个化简 \(x^2\bmod (y^2-xy)\) 可以得到其就是 \(\gcd(x,y)\)

\(n\) 非常大难以入手,可以考虑直接枚举 \(d=y-x=\gcd(x,y)\),再枚举 \(d\) 的倍数 \(kd\),这个时候可以得到 \(x=kd,y=(k+1)d\),验证是否有 \(kd \oplus (k+1)d=d\) 即可,统计 \(k\) 的个数为 \(c\)。让答案累加上 \(c\times d^2\) 即可。这样子可以得到 \(50 \rm pts\)

注意到上一个做法,我们并没有利用到 \(kd\subset (k+1)d\) 这个条件。记 \(2^w\)\(>d\) 的最小 \(2\) 的次幂数,不难发现上述条件的成立只与 \(k\) 的前 \(w\) 位有关,于是对于 \(k\bmod 2^w\) 有周期,直接计算是 \(O(m^2)\) 的,可以拿到 \(80 \rm pts\)。模拟赛考场上止步于此。

但是赛后伟大的字典序队长 & 韩国队长 & 省队P话队长 FS_NEO 告诉我们,这个 \(O(m^2)\) 的做法其实是可以拿下满分的。因为我们打个表找到规律(一个周期内的答案是 \(2\) 的次幂),就可以 \(O(1)\) 计算一个完整周期内的答案,然后对于不足一个周期的部分直接枚举算。虽然理论复杂度还是 \(O(m^2)\),但是之前是要完整枚举一个周期,而这次只要枚举不足一个周期的一部分,跑不满,所以可以冲过去。再次拜谢 FS_NEO 爆杀紫题。

现在讲述正解,赛场上我的 \(kd\subset (k+1)d\) 还是有点难看了,其实这个就是 \(d\subset (k+1)d\)

得到 \(d\subset (k+1)d\) 之后,我们直接枚举 \((k+1)d \bmod 2^w\) 要求其为 \(d\) 的超集。记 \(k=\log_2m\),原本枚举两个二进制数是 \(2^k\times 2^k=4^k\) 的(也就是 \(m^2\)),但是我们枚举所有二进制数的所有超集,之后复杂度变成了 \(O(3^k)\) 的!

对于 \((k+1)d\bmod 2^w=z\)\(k\) 计数,通过 \(y=(k+1)d\) 可以得到

\[\begin{cases} y\equiv 0\pmod d\\ y\equiv z\pmod {2^w} \end{cases}\]

使用 ExCRT 求解个数即可。时间复杂度 \(O(m\log m+3^{\log m})\)

原根

  • 下文默认 \((a,m)=1\),因为 \(a,m\) 互质是 \(a\)\(m\) 的阶存在的充要条件。

满足同余式,\(a^r \equiv 1 \pmod m\) 最小的正整数 \(r\),是 \(a\)\(m\) 的阶。记作,\(r=\delta_m(a)\)

由欧拉定理,\(a^{\varphi(m)} \equiv 1\pmod m\),因此阶存在,且其大小 \(\le \varphi(m)\)

性质\(a~a^2~a^3...a^{\delta_m(a)}\)\(m\) 两两不同余,可以将 \(a\) 的幂次看成一个模 \(\delta_m(a)\) 的循环节。

可以得到推论,\(a^x\equiv a^y \pmod m\),当且仅当 \(x\equiv y\pmod {\delta_m(a)}\)

因此对于质数 \(p\),连边 \((i,(ia)\bmod p)\) 可以形成 \(\dfrac{p-1}{\delta_p(a)}\) 个长度为 \(\delta_p(a)\) 的环。

寻找阶:找阶可以用 BSGS 或者对于 \(\varphi(m)\) 不断除掉质因子(利用 \(\delta_m(a)\mid \varphi(m)\))。

原根

\(\delta_m(g)=\varphi(m)\) 时,则称 \(g\)\(m\) 的一个原根。注意原根是底数。

对于一般情况,\(g\) 的次幂可以取遍 \([0,m-1]\) 之内的质数,也就是可以取到 \(m\) 的剩余系。

因此由上述性质可知,\(m\) 为质数\(g\)\(m\) 的原根的时候,有 \(g~g^2...g^{m-1}\)\(m\) 两两不同余。

需要记住 998244353 的原根是 3。
只有 \(2,4,p^k,2\times p^k\)(其中 \(p\) 为奇质数)才有原根。

应用

  • NTT 中 \(w_n=g^{\frac{p-1}{n}}\pmod m\)

  • 对于解与模数互质且模数存在原根的方程,我们可以利用原根转乘法为加法。

P6091 【模板】原根

首先结论是 \(n\) 的原根的级别大概是 \(O(n^{0.25})\) 的。所以直接枚举即可,下面要解决的就是判定。

必要条件是 \(g^{\varphi(n)} \equiv 1\pmod n\)。然后必须验证 \(\forall k < \varphi(n)~~g^k \not \equiv 1 \pmod n\)。枚举验证显然太慢了,我们还有一条性质,如果存在上述 \(k\),那么,满足 \(k\mid \varphi (n)\)

所以我们只需要验证所有\(\frac{\varphi(n)}{p_i}\) 即可。

在求得最小原根之后,其他的原根都形如 \(g^k\) 的形式,满足 \(\gcd(\varphi(n),k)=1\) 故个数为 \(\varphi(\varphi(n))\) 的。

P12694 BZOJ2219 数论之神

\(P=2\times k+1\),题目即求 \(x^a\equiv b\pmod P\)\([0,P)\) 之内解的个数。

首先,我们并不擅长做普通情况模数,于是将 \(P=\prod p_i^{c_i}\) 进行质因数分解。然后对于每个 \(i\) 求解 \(x^a\equiv b\pmod {p_i^{c_i}}\)\([0,p_i^{c_i})\) 中解的个数,根据 CRT 相关的理论,我们可以将解的个数乘在一起得到最后总的解的个数。

\(a\) 在指数也不好处理,由于 \(p^k\) 存在原根所以我们可以使用原根 \(g\) 转化为对于指数的讨论。

但是当 \(a,b\)\(p^k\) 不互质的时候,不能直接取原根。需要分类讨论。

  • \(\gcd(b,p^k)=1\)

此时我们可以得到 \(\gcd(a,p^k)=1\)

\(x=g^c,b=g^d\),可以得到 \(g^{ca}\equiv g^{d}\pmod {p^k}\)。这个时候指数就在模阶的意义下相等了,同时由于 \(g\) 是原根,所以就是在模 \(\varphi(p^k)\) 的意义下相等了。

上述同余式可以直接改写为 \(ca\equiv d\pmod {\varphi(p^k)}\)。根据裴蜀定理,有解的充要条件是 \(\gcd(a,\varphi(p^k)) \mid d\)。如果有解,那么 \(c\in[0,\varphi(p^k))\) 的解的个数为 \(\gcd(a,\varphi(p^k))\)

  • \(p^k\mid b\)

这种情况非常简单,可以直接得到 \(x^a\equiv 0\pmod {p^k}\)。设 \(x\)\(p\) 的幂次为 \(w\),那么有 \(w\ge \lceil\dfrac{k}{a}\rceil\)。由于 \(p^{w_{\min}}\mid x\),所以 \(x\) 的取值有 \(p^{k-\lceil\frac{k}{a}\rceil}\) 种。

  • \(v_p(b)<k\)

\(w=v_p(b)\),可以使用同余式的除法。由于同余的性质,有 \(\gcd(x^a,p^k)=\gcd(b,p^k)=p^w\),在等式两边都除以 \(p^w\) 可以得到 \(\dfrac{x^a}{p^w}\equiv \dfrac{b}{p^w} \pmod {p^{k-w}}\)。由于 \(\gcd(x^a,p^k)=p^w\),所以 \(a\mid w\),故上式可以改写为 \((\dfrac{x}{p^{\frac{w}{a}}})^a\equiv \dfrac{b}{p^w}\pmod {p^{k-w}}\),这个时候满足互质性质,可以直接用第一种情况里面的方法求解答案。注意由于我们把值域缩小成了原先的 \(\dfrac{1}{p^{w-\frac{w}{a}}}\),所以最后的答案还要乘以 \(p^{w-\frac{w}{a}}\)。别忘记那个 \(-\frac{w}{a}\),因为括号内部的 \(x\) 除以了 \(p^{\frac{w}{a}}\)

离散对数

在模 \(p\) 的意义下求解 \(\log_ab\),也就是求 \(x\),满足 \(a^x\equiv b\pmod p\)

P3846 [TJOI2007] 可爱的质数/【模板】BSGS

\(\gcd(a,p)=1\) 的时候,如果 \(a^x\equiv n\bmod p\) 有解,根据扩展欧拉定理那么一定存在一个解 \(< \varphi(p)\)

\(x=uB-v\),枚举 \(u,v\) 然后放到 std::map 里面匹配即可,

P4195 【模板】扩展 BSGS/exBSGS

\(\gcd(a,p)\neq 1\) 的时候,我们需要将其转化为 \(\gcd(a,p)=1\) 的情况。

\(a^x\equiv b\pmod p\),看成同余方程 \(a^x+kp=b\),令 \(d=\gcd(a^x,p)\) 其有解的充要条件是 \(d\mid b\),于是我们不断在等式两边除以 \(d\),直到 \((a,p)=1\)。令 \(D=\prod\limits_{i=1}^cd_i\),则等式为 \(a^{x-c}\dfrac{a^c}{D}+k\dfrac{p}{D}=\dfrac{b}{D}\)

我们令 \(a'\gets a,p'\gets \dfrac{p}{D},b'\gets \dfrac{b}{D}\),乘上 \(\dfrac{a^c}{d}\) 的系数之后就可以使用 BSGS 了。

QOJ8706. 解方程

很妙的一题,注意到后面那一坨实在难以处理,但是数据随机生成,所以考虑进行一步放缩,把最后的一部分放缩掉,我们可以得到 \(a_ix\in [c_i-10^{11},c_i]\),数据随机情况下所以我们选择前两个方程,可以保证满足这两个约束的 \(x\) 的个数大约为 \((\dfrac{10^{11}}{P})^2\times P=10^4\) 这个量级,这样子我们只要找到所有满足条件的 \(x\),再验证 \(m\) 个方程即可。

如何找到所有符合条件的 \(x\),BSGS!具体来说就是,我们先把第一个方程调整成 \(x\in [0,R]\) 的形式(这一步可以令 \(x\gets a_1x-(c_1-10^{11})\),最后再变回去)。然后对于第二个方程是 \(a_2x\in [c_2-10^{11},c_2]\),令 \(B=\sqrt {10^{11}}\),预处理 \(x\in [0,B]\)\(a_2x\bmod P\) 排序。枚举 \(i\in [0,B]\),对于 \(a_2iB\) 在排序数组中二分找到所有满足条件的数,组合出 \(x\) 之后进行 check。之前说了满足条件的 \(x\) 的期望个数为 \(1000\),所以 BSGS 暴力找到所有解并且检验的复杂度是正确的。

除了上述讲的做法,还存在一种类欧解法

欧拉函数

\[\varphi(xy)=\varphi(x)\varphi(y)\dfrac{d}{\varphi(d)} \]

欧拉定理

\[a^{\varphi(p)}\equiv 1\pmod p \]

\(p\) 为质数的时候,\(\varphi(p)=p-1\),等价于费马小定理。

扩展欧拉定理

\[a^b\equiv \begin{cases} a^{b\bmod \varphi(p)+\varphi(p)} & b> \varphi(p) \\ a^b & b\le \varphi(p) \end{cases} \pmod p\]

特别地,当 \(\gcd(a,p)=1\) 的时候,可以直接对于指数用 \(\varphi(p)\) 取模。

P4139 上帝与集合的正确用法

递归 \(+\infty\) 次的幂塔,利用扩展欧拉定理递归求解,时间复杂度 \(O(\log p)\)。对于任意大于 \(1\) 的整数,\(\varphi(p)\) 为偶数。而对于偶数 \(p\) 的欧拉函数有 \(\varphi(p)\le \dfrac{p}{2}\)

由于幂塔是递归无线层的,所以肯定 \(>\varphi(p)\),所以直接取第二种情况即可。

int tower(int a,int n,int p){
    if(p==1) return 0;
    int t = phi(p);
    else return qpow(a,tower(a,t)+t,p);
}

P3747 [六省联考 2017] 相逢是问候

观察 \(a_i\) 的变化过程:\(a_i\to c^{a_i}\to c^{c^{a_i}}\dots \to c^{c^{c^{\dots^{a_i}}}}\)

这是一个幂塔不断叠的过程,但是注意由于不是无限递归,所以其指数并不一定 \(>\varphi(p)\),所以我们在递归求幂塔的时候我们不能像无穷幂塔那样子无脑直接取第二种情况了,因为会有情况 \(1\) 的出现。所以我们需要求出 \(c^{c^{c^{\dots^{a_i}}}}\) 的满足 \(\le p\) 前若干项,这样子可以在求幂的时候快速判断当前指数与 \(\varphi(p)\) 大小关系。

int tower(int i,int k,int id){
	if(id==lim) return 0;
	if(k==0) return a[i]%phi[id];
	if(C==1||(k-1<=up[i]&&p[k-1][i]<phi[id+1])) return qpow(tower(i,k-1,id+1),id);
	else return qpow(tower(i,k-1,id+1)+phi[id+1],id);
}

这是一个求幂塔的基本代码,其中 \(id\) 代表的是 \(p,\varphi(p),\dots\) 的一系列数的数组下标,其中 \(\varphi_{lim}=1\),所以递归到 \(id\)\(lim\) 的时候就是到了底层,这个时候 \(\bmod 1\),直接返回 \(0\) 即可。同样指数为 \(0\) 的时候也可以直接返回 \(a_i\) 取模结果。否者我们将运用扩展欧拉定理,特判掉 \(c=1\) 的情况后,我们只需要判断后续的指数与 \(\varphi(v_{id})\) 的大小关系即可,其中 \(v_{id}\) 是当前这一层的模数。

关于上一段中的后续指数的大小,也就是我之前说的需要对于每个 \(a_i\) 都预处理 \(c^{c^{c^{\dots^{a_i}}}}\) 的前若干项,如果后续项数超出了预处理的项数就代表一定超过了当前的 \(\varphi(v_{id})\),否则拿之前预处理的结果和 \(\varphi(v_{id})\) 比较即可。

其中 tower 函数中的 qpow 如果直接计算,会多一个 \(\log\) 的代价。这里需要用到光速幂,也就是如果直接计算 \(x^k\) 可以快速幂,但是如果我们想 \(O(1)\) 回答就可以使用 \(O(\sqrt k\log k)\) 预处理,\(O(1)\) 回答的光速幂,我们预处理 \(x^{0},x^1,\dots x^{B-1}\)\(x^{B},x^{2B}\dots x^{B^2}\),其中 \(B=\sqrt k\)。这样子 \(k=k\bmod B+\lfloor\dfrac{k}{B}\rfloor\times B\),直接用预处理的两个信息相乘回答即可。

void init(){
	phi[lim=1]=P;
	while(phi[lim]>1) phi[lim+1]=getphi(phi[lim]),lim++;
	for(int i=1;i<=lim;i++){
		p1[i][0]=1;
		for(int j=1;j<=B;j++) p1[i][j]=1ll*p1[i][j-1]*C%phi[i];
		int z=p1[i][B]; p2[i][0]=1;
		for(int j=1;j*B<=2*P;j++) p2[i][j]=1ll*p2[i][j-1]*z%phi[i];
	}
	int z=0; c[z]=1; 
	while(c[z]<P&&z<=30) z++,c[z]=c[z-1]*C;
	z--;
	for(int i=1;i<=n;i++){
		p[up[i]=0][i]=a[i];
		while(up[i]<=z&&p[up[i]][i]<=z) p[up[i]+1][i]=p1[1][p[up[i]][i]],up[i]++;
	}
}

这是预处理的代码,一段是求出所有 \(p,\varphi(p),\varphi(\varphi(p))\dots\),这些数的个数不超过 \(\log p\) 个。然后预处理光速幂。最后是处理 \(c^{c^{c^{\dots^{a_i}}}}\) 的前若干项。

有了以上的基础,我们已经会处理题目中的数论操作了,但是我们需要使用一个高效的结构来维护。

这里采用线段树,线段树可以轻松完成区间求和的任务。一般遇到区间修改,线段树都是把所要求的区间 \([ql,qr]\) 分裂成 \(O(\log n)\) 个极大的节点区间进行整体修改,但是本题,可以发现我们无法维护进行一次幂塔操作之后区间所有数和的变化,只能递归到单点来暴力修改。还是需要上面的性质,幂塔只会递归 \(\log p\) 层,也就是说我们对于每个点的修改次数不超过 \(\log p\) 次,只需要暴力修改时间复杂度就是对的!所以我们对于每个线段树节点维护区间和,及其区间被操作次数最少的点的操作次数,只要哪个区间存在没有达到操作上界的点就暴力往这个区间中这些点的位置进行递归即可,每个叶子节点只会被保留修改 \(\log p\) 次。

时间复杂度 \(O(n(\log n\log p+\log^2p))\)。第一个 \(\log n\log p\) 是线段树操作所自带的 \(\log\) 复杂度和每个点被暴力递归到的次数。后面的 \(\log^2p\) 是每个点的操作次数乘以单次操作的时间复杂度(也就是求解幂塔的时间复杂度),其实我们可以通过提前处理 \(\rm tower\) 数组来把这个 \(\log^2p\) 变成 \(\log p\),但是意义不大,因为一是这样子需要开 \(O(n\log^2p)\) 的空间,二是我们已经有了第一项 \(\log n\log p\) 的存在,即使这边去掉一个 \(\log\) 也避免不了复杂度为 \(2\log\) 的事实。

附录:幂塔暴力算法。

int qpow(ll x,int k,int mod){
	if(!x) return mod; ll res=1;
	for(;k;k>>=1){
		if(k&1){
			res=res*x;
			if(res>=mod) res=res%mod+mod;
		}
		x=x*x; if(x>=mod) x=x%mod+mod;
	}
	return res;
}
int tower2(int i,int k,int id){
	if(id==lim) return 1;
	if(k==-1) return a[i]>=phi[id]?a[i]%phi[id]+phi[id]:a[i];
	if(vec[i][k]==0) return a[i]%phi[id];
	return qpow(vec[i][k],tower2(i,k-1,id+1),phi[id]);
}
posted @ 2024-02-01 00:35  Mirasycle  阅读(38)  评论(0)    收藏  举报