【学习记录】数学

· · 个人记录

数学啥都不会,最近根据三轮省集 Day6 课件写了几个板子,证明也没咋看。因此本文不包含任何证明,只是记录一下做法方便日后复习。

暂时先写这么多,之后可能会补充,之前的几篇记录也一样。

线性预处理逆元

[1,n] 中所有数对 p 取模的逆元,可以递推求解。具体地,设 p=ik+r,0\le r <i,即 pi 的带余除法运算。因此有 ik=-r,\frac 1i=-\frac kr,即 inv_i=(p-\lfloor\frac pi\rfloor)inv_{p\bmod i} \bmod p,代码。

n 个数 a_ip 取模的逆元,可以类似阶乘预处理出 s_i=\prod_{j=1}^i a_j,并求出 s_n 的逆元,再倒着推出所有 s_i 的逆元 s'_i。这样 a_i 的逆元即为 s'_i s_{i-1}\bmod p,代码。事实上上个问题也能这么做。

扩展欧几里得算法(Exgcd):P5656

给定 a,b,c,求解 ax+by=c 的整数解 (x,y)。根据裴蜀定理,当且仅当 \gcd(a,b)\mid c 时有解。因此先求解 ax+by=\gcd(a,b),根据辗转相除法有 \gcd(a,b)=\gcd(b,a\bmod b),b\ne 0,因此列出另一个式子 bx'+(a\bmod b)y'=ax+by。将 a\bmod b 写成 a-\lfloor\frac ab\rfloor b,合并 a,b 同类项得到 ay'+b(x'-\lfloor\frac ab\rfloor y')=ax+by,据此可以递归求出 x',y' 再反推出 x,y,在 b=0 时返回 x=1,y=0,即可得到一组可行解 x,y

\gcd(a,b)=g,此时有 X=\frac {cx}g,Y=\frac{cy}g 为满足题意的一组解。有时会在一些限制下求 X,Y 的最值,只需要知道所有解均满足 X'=X+\frac{kb}g,Y'=Y-\frac{ka}g 即可,容易求最小正整数解之类的最值,时间复杂度 O(\log V),代码。

中国剩余定理(CRT):P1495

给出 n 个同余方程 x\equiv b_i\pmod {a_i}a_i 两两互质,求满足所有方程的最小非负整数 x。考虑在不影响其他限制的前提下满足第 i 个限制。具体地,设 M=\prod_{i=1}^n a_i,c_i=\frac M{a_i},即 c_i 为除 i 外的所有模数之积。之后求出 c_i 在模 a_i 意义下的逆元 c_i^{-1},最后求出 r=\sum_{i=1}^n c_ic_i^{-1}b_i 即为可行解,对 M 取模可得最小解。

这里可以感性理解,每一项由于有 c_i 作为系数,不会对其他方程造成影响;而在模 a_i 意义下为 b_i,满足了该方程的限制。由于用到了逆元,要求模数两两互质,求逆元使用 Exgcd 即可,时间复杂度 O(n\log V),代码。据说拉格朗日差值也是类似思想。

扩展中国剩余定理(ExCRT):P4777

题意同上,然而不再保证模数互质。考虑直接暴力合并两个方程,可将原式化为 x-k_ia_i=b_i,x=k_ia_i+b_i。因此若有 A,Ba,b 两个方程,则有 AK+B=ak+b,即 ak-AK=B-b,其中只有 k,K 未知,可以直接代入 a,A,B-b 用 Exgcd 求出 k,K 的解。之后求出 b'=b+ka,a'=\frac{aA}gb'a' 取模后得到的 a',b' 方程即与上面两个方程等价。

每次合并两个方程,直到只剩一个为止,最终的 b 即为最小非负解。时间复杂度 O(n\log V),代码。所以其实 ExCRT 和 CRT 完全没啥关系,泛用性高的同时可能还容易一些。

卢卡斯定理(Lucas):P3807

给出 n,m,p,求 {n+m\choose n}\bmod pp 为质数。卢卡斯定理即 {n\choose m}\bmod p={n\bmod p\choose m\bmod p}\times {{\lfloor\frac np\rfloor}\choose {\lfloor \frac mp \rfloor}},还有一种用 p 进制的写法,两种是等价的。因此求组合数时可以不断递归,直到 n,m 均小于 p 时再暴力求解。这里若预处理 p 以内的阶乘及其逆元,可以 O(1) 计算。时间复杂度 O(p+\log_pV),代码。

扩展卢卡斯定理(ExLucas):P4720

题意同上,然而不再保证模数 P 为质数。考虑把组合数拆成阶乘形式 \frac{n!}{m!(n-m)!},然而模数不为质数时不一定有逆元。因此将模数 P 质因数分解为若干 p^k,求出这些 {n\choose m}\bmod p^k 的值,再用 ExCRT 合并出答案。

考虑如何求该值,先把所有 p 全拿出来,即变为 \frac{\frac {n!}{p^x}}{\frac{m!}{p^y}\times \frac{(n-m)!}{p^z}}\times p^{x-y-z}。现在需要快速求 n! 中除掉所有 p 因子后对 p^k 取模的结果,以及除去的 p 因子个数,分别设这两个值为 f(n),g(n)。显然有 g(n)=g(\lfloor\frac np\rfloor)+\lfloor\frac np\rfloor,以及 f(n)=f(\lfloor\frac np\rfloor)+\lfloor\frac np\rfloor s_{p^k}+s_{n\bmod p},其中 s_i 表示 [1,i] 中不为 p 倍数的所有数乘积,可以 O(p^k) 预处理出来。含义即先将 p 的倍数取出并除以 p,在 f(n) 计算时还用到了模 p^k 的循环节性质。

这样答案即为 \frac{f(n)}{f(m)f(n-m)}\times p^{g(n)-g(m)-g(n-m)}\bmod p^k,由于 f 值中不含 p 因子,一定与 p^k 互质,可以直接用 Exgcd 计算逆元。总时间复杂度可以分析到 O(P\log P),代码。所以其实 ExLucas 和 Lucas 基本没啥关系,泛用性高的同时可能还容易一些。

大步小步算法(BSGS):P3846

给定质数 pb,n,求最小非负整数 l 使得 b^l\equiv n\pmod p。显然答案不会超过 p,因为 p 次后一定会出现循环节。考虑设 B=\sqrt p,l=kB-t,t<B,有 b^{kB-t}\equiv n\pmod p。由于 p 为质数,一定存在逆元,可以直接除过去得到 b^{kB}\equiv nb^t\pmod p。这时两边都只有 O(\sqrt p) 种取值,枚举出来找到相等的最小 kB-t=l 即可。时间复杂度为 O(\sqrt p)O(\sqrt p\log p),代码。

扩展大步小步算法(ExBSGS):P4195

题意同上,然而不再保证 p 为质数。由于 b,p 不一定互质,可能出现没有逆元的情况。考虑去掉 b,p 的公因子,具体地,先改写成 b^l-tp=n,即 b\times b^{l-1}-pt=n,这时求出 d=\gcd(b,p),若 d\nmid n 则无解,否则可将 b,p,n 同除 d。之后若 gcd(b,p) 仍不为 1 则重复此操作,直到 b,p 互质。

这时得到的式子转化回去为 Kb^{l-k}\equiv n\pmod p,其中 b,p 互质,Kkb 消掉公因子后剩余部分之积对最终 p 取模的结果。此时就可以直接使用普通 BSGS 解决了,求出答案加上 k 即为最终答案。注意要特判答案不超过 k 的情况,只需在 K=n 时确定目前 k 为答案即可。时间复杂度为 O(\log p+\sqrt p),代码。所以 BSGS 的扩展是转化为能解决的有逆元情况,再套用普通 BSGS 求解的,比之前的两组算法关系密切得多。

求欧拉函数

若要预处理 [1,n] 内的欧拉函数,可以使用线性筛法,令质数 p\varphi(p)=p-1,在筛时若 p_j\mid i,则令 \varphi(ip_j)=\varphi(i)\times p_j,否则令 \varphi(ip_j)=\varphi(i)\times \varphi(p_j)=\varphi(i)\times(p_j-1),这里基于每个质因子 p 都会给欧拉函数值乘上 \frac{p-1}p。代码:

phi[1]=1;
for(int i=2;i<=P;i++)
{
    if(!f[i]) p[++ct]=i,phi[i]=i-1;
    for(int j=1;j<=ct&&1ll*i*p[j]<=P;j++)
    {
        f[i*p[j]]=1;
        if(i%p[j]==0)
        {
            phi[i*p[j]]=phi[i]*p[j];
            break;
        }
        phi[i*p[j]]=phi[i]*(p[j]-1);
    }
}

若要求单个数的欧拉函数值,则可以直接枚举其所有质因子,并按照上面所说的 \frac{p-1}p 计算出答案。代码见下一题的提交记录。

扩展欧拉定理:P5091

a^b\bmod m,其中 m\le 10^{8},a\le 10^9,b\le 10^{2\times 10^7}。扩展欧拉定理即为:

当然 $\gcd(a,m)=1$ 时有欧拉定理 $a^{\varphi(m)}=1,a^b\equiv a^{b\bmod \varphi(m)}\pmod m$。 因此类似快读读入 $b$ 的每一位,过程中一直对 $\varphi(m)$ 取模即可。时间复杂度为 $O(\sqrt m+\lg(b)+\log m)$,分别为求欧拉函数,读入和快速幂的复杂度,[代码](https://www.luogu.com.cn/record/220614996)。 ### 拉格朗日插值:P4781 给出 $n$ 个点 $(x_i,y_i)$,保证 $x_i$ 互不相同,求一个 $(n-1)$ 次多项式使得 $\forall i,f(x_i)=y_i$,$n\le 2000$。考虑对每个点构造一个多项式 $g_i(x)$,使得 $g(x_i)=y_i,\forall j\ne i,g(x_j)=0$,则 $\sum g_i$ 即为合法的 $f$。一种合法构造为 $g_i(x)=y_i\cdot\prod_{j\ne i} \frac{x-x_j}{x_i-x_j}$,本题直接带入计算即可。若需要求出多项式 $f(x)$ 的系数,可以先计算出 $a_i=\frac{y_i}{\prod_{j\ne i}x_i-x_j}$,再预处理出多项式 $t(x)=\prod x-x_i$ 的系数,每次先求出 $g(x)=\frac{t(x)}{x-x_i}$,再将 $a_i\cdot g(x)$ 加给 $f(x)$ 即可。时间复杂度 $O(n^2)$,[提交记录](https://www.luogu.com.cn/record/231521811)。更低复杂度需要多项式科技,不学。 ### 莫比乌斯反演 定义 $i$ 存在平方因子时 $\mu(i)=0$,否则若其质因子个数为 $k$,$\mu(i)=(-1)^k$。 莫比乌斯函数 $\mu$ 可线性筛求出,有 $\mu(1)=1,\mu(p)=-1$。否则有 $x=i\cdot y$,其中 $y$ 为 $x$ 最小质因子,则若 $y\mid i$,$\mu(x)=0$,否则 $\mu(x)=-\mu(i)$。 定义狄利克雷卷积运算 $\ast$ 为 $h=f\ast g$ 时 $h(x)=\sum_{d\mid x} f(d)g(\frac xd)$。 定义数论函数 $id(x)=x,1(x)=1,\varepsilon(x)=[x=1]$。 有性质 $\sum_{d\mid n}\mu(d)=[n=1]=\varepsilon(n)$,即 $\mu\ast1=\varepsilon$。 还有性质 $\sum_{d\mid n}\varphi(d)=n$,即 $\varphi \ast1=id$。 上式两边卷上 $\mu$ 得到 $\varphi\ast\varepsilon=id\ast\mu$,展开得到 $\varphi(n)=\sum_{d\mid n}d\cdot\mu(\frac nd)$。 #### P4450 双亲数 $T\le 5\times 10^4$ 次询问,每次给定 $A,B,d\le 5\times 10^4$,求 $\sum_{i=1}^A\sum_{j=1}^B [\gcd(i,j)=d]$。先将 $i,j$ 均除掉 $d$,得到 $\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[\gcd(i,j)=1]$,将其用性质展开得到 $\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}\sum_{k\mid\gcd(i,j)}\mu(k)$。交换求和号,将 $k$ 放在最前面,得到 $\sum_{k=1}^{\lfloor\frac{\min(A,B)}d\rfloor}\sum_{i=1,k\mid i}^{\lfloor\frac Ad\rfloor}\sum_{j=1,k\mid j}^{\lfloor\frac Bd\rfloor} \mu(k)$。该式的值显然为 $\sum_{k=1}^{\lfloor\frac{\min(A,B)}d\rfloor}\mu(k)\lfloor\frac A {dk}\rfloor\lfloor\frac B {dk}\rfloor$。 线性筛出所有 $\mu $ 的值,本题已经可以做到单次查询线性。然而多次询问时无法通过。考虑对后面的部分整除分块,则两个除式各有 $O(\sqrt V)$ 种取值,两式均不变的连续段数量也是 $O(\sqrt V)$ 级别的。因此对 $\mu$ 预处理前缀和即可做到 $O(V+T\sqrt V)$ 的复杂度,[提交记录](https://www.luogu.com.cn/record/235081106)。 #### P2257 YY的GCD $T\le 10^4$ 次询问,每次给定 $n,m\le10^7$,求 $i\in[1,n],j\in[1,m]$ 中有多少对 $(i,j)$ 满足 $\gcd(i,j)$ 为质数,设质数集合为 $P$。直接列出式子 $\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)\in P]$,并改为先枚举质数为 $g$,得到 $\sum_{g=2,g\in P}^{\min(n,m)}\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)=g]$,然后用上题的过程拆开得到 $\sum_{g=2,g\in P}^{\min(n,m)}\sum_{k=1}^{\lfloor\frac{\min(A,B)}g\rfloor}\mu(k)\lfloor\frac A {gk}\rfloor\lfloor\frac B {gk}\rfloor$。 令 $T=gk$,则原式变为 $\sum_{T=2}^{\min(n,m)}\lfloor\frac AT\rfloor\lfloor\frac BT\rfloor \sum_{g\mid T,g\in P}\mu(\frac Tg)$,需要求出 $f(T)=\sum_{g\mid T,g\in P}\mu(\frac Tg)$。考虑在线性筛过程中预处理,有 $f(1)=0,f(p)=1$。否则有 $x=iy$,其中 $y$ 为 $x$ 的最小质因子。若 $y\mid i$ 则 $g\ne y$ 时 $\frac xg$ 包含 $y^2$ 因子,一定没有贡献,因此只有 $g=y$ 有贡献 $f(x)=\mu(i)$;否则 $f(x)=\sum_{g\mid T,g\in P}\mu(\frac Tg)+\mu(i)=\sum_{g\mid i}\mu(\frac {iy}g)+\mu(i)=-f(i)+\mu(i)$。之后对 $f$ 求前缀和并整除分块求解即可,时间复杂度 $O(V+T\sqrt V)$,[提交记录](https://www.luogu.com.cn/record/235108385)。 #### P2398 GCD SUM 给定 $n\le 10^7$,求 $\sum_{i=1}^n\sum_{j=1}^n \gcd(i,j)$。直接拆并转化成 $\sum_{g=1}^n g\cdot\sum_{k=1}^{\lfloor\frac ng\rfloor}\mu(k)(\lfloor\frac n {gk}\rfloor)^2$,同样令 $T=gk$ 得到 $\sum_{T=1}^n(\lfloor\frac n {T}\rfloor)^2 \sum_{g\mid T}g\cdot\mu(\frac Tg)$,~~然后试图爆推线性筛式子失败了~~。事实上上面有性质表明 $\sum_{g\mid T}g\cdot\mu(\frac Tg)=\varphi(T)$,因此线性筛欧拉函数即可做到 $O(n)$ 和多组 $O(n+T\sqrt n)$ 的复杂度,[提交记录](https://www.luogu.com.cn/record/235512926)。 ### 狄利克雷前缀和:P5495 用于解决求 $b_i=\sum_{j\mid i}a_j$ 或 $c_i=\sum_{i\mid j}a_j$ 的问题及其逆问题,时间复杂度 $O(n\ln \ln n)$。该问题的暴力做法为枚举每个数的倍数,时间复杂度 $O(n\ln n)$。 考虑以每种质因子为一维,此时每个下标是高维内一个点,$i$ 的因数是每一维均不大于其的点,倍数是每一维均不小于其的点。因此在该意义下对 $a$ 数组做高维前缀和即可得到 $b$,做高维后缀和即可得到 $c$。具体实现仍然在一维数组内,枚举每个质因数 $p$,并按某种顺序枚举所有 $ip\le n$ 更新即可。注意前缀和正序,后缀和逆序枚举,逆问题差分时与原问题顺序相反。时间复杂度分析方式同埃氏筛,~~我都不会~~,是 $O(n\ln\ln n)$ 的,[提交记录](https://www.luogu.com.cn/record/236652379)。 #### U540870 课后习题 2 给定长为 $n$ 的序列 $a$,求序列 $b$ 使得 $b_i=a_i+\sum_{j\mid i,j<i} b_j$。$n\le 2\times 10^7$。注意到 $j\mid i,j<i$ 的 $j$ 一定不超过 $\lfloor\frac i2\rfloor$,因此通过值域倍增的方式来保证计算 $b_i$ 时所需 $b_j$ 的值均已确定。 具体地,设 $m$ 表示目前 $[1,m]$ 内的 $b_i$ 均处理好了。每次取 $m'=\min(2m,n)$,然后处理 $[m+1,m']$ 内的所有 $b$。此时先将 $[1,m]$ 内的 $b$ 复制一份到 $t$ 中,之后在 $t$ 上做 $[1,m']$ 的狄利克雷前缀和,得到的 $t_i,i\in[m+1,m']$ 即为 $\sum_{j\mid i,j<i} b_j$,因此有 $b_i=a_i+t_i$,这样就完成了这部分 $b$ 的求解,最后更新 $m=m'$ 即可。 下面分析时间复杂度,大概是 $\sum_{i=0,2^i\le n} O(2^i\ln\ln(2^i))$,在 $i$ 最大时的取值大概为 $O(n\ln\ln n)$,且 $i$ 较小的情况下复杂度总和不超过该值,这是由于 $\sum_{j=0}^{i-1} 2^j=2^i-1$。因此总时间复杂度仍是 $O(n\ln\ln n)$ 的,[提交记录](https://www.luogu.com.cn/record/236916679)。 ### 万能欧几里得:P5170 用于解决 $\lfloor\frac{ai+b}c\rfloor$ 结构的数列求和问题,类欧几里得算法可以解决,然而这个更万能。注意到该式实际上相当于求直线 $y=\frac{ax+b}c$ 及其下方,$x$ 轴上方且横坐标在 $[0,n]$ 内的点数(点权和)。于是根据直线穿过网格线的过程可写出一个串,对该串进行计算。 具体地,直线每次穿过横线就写下一个 U,每次穿过竖线就写下一个 R。特别地,穿过整点时先 U 再 R,这是由于直线上的点也会贡献;字符串开头要补上 $\lfloor\frac bc\rfloor$ 个 U,表示截距处已经穿过的横线数量。此时依次操作每个字符,U 就将纵坐标 $y$ 增加,R 就用当前纵坐标 $y$ 贡献一次,最终得到的值即为答案。 万能欧几里得的基本思路,就是将操作序列中的 U,R 视作某个幺半群中的元素 $U,R$,将操作序列视为幺半群元素乘积,最终得出答案。其约化问题的手段是将操作分批次合并,记字符串对应操作乘积为 $f(a,b,c,n,U,R)$,过程具体如下: - 若 $b\ge c$,操作序列开头有 $\lfloor\frac bc\rfloor $ 个 U,直接计算乘积并移除,此时第 $i$ 个 R 前面的 U 数量变为 $\lfloor\frac{ai+b}c\rfloor-\lfloor\frac bc\rfloor=\lfloor\frac{ai+(b\bmod c)}c\rfloor$,于是得到 $U^{\lfloor\frac bc\rfloor}f(a,b\bmod c,c,n,U,R)$。 - 若 $a\ge c$,操作序列中每个 R 与上一个之间至少有 $\lfloor\frac ac\rfloor$ 个 U,可将其合并到 R 上,此时第 $i$ 个 R 前面的 U 数量变为 $\lfloor\frac{ai+b}c\rfloor-\lfloor\frac ac\rfloor i=\lfloor\frac{(a\bmod c)i+b}c\rfloor$,于是得到 $f(a\bmod c,b,c,n,U,U^{\lfloor\frac ac\rfloor}R)$。 可以发现上面两种变化独立,可写成 $f(a,b,c,n,U,R)=U^{\lfloor\frac bc\rfloor}f(a\bmod c,b\bmod c,c,n,U,U^{\lfloor\frac ac\rfloor}R)$,以下讨论 $a,b\lt c$ 的情况,核心思想是反转横纵坐标,实现 $a,c$ 的交换,再使用上面的变化将参数变小。显然新串的 $n'=\lfloor\frac{an+b}c\rfloor=m$。 现计算翻转前第 $j$ 个 U 前方的 R 数量,就等于最大的 $i$ 满足 $\lfloor\frac{ai+b}c\rfloor\lt j$,即 $i\lt\lceil\frac{cj-b}a\rceil=\lfloor\frac{cj-b-1}a\rfloor+1$,于是 $i=\lfloor\frac{cj-b-1}a\rfloor$。由于此时 $b'=-b-1$,考虑将原串中第一段 $R^{\lfloor\frac{c-b-1}a\rfloor}U$ 提出来,之后第 $j$ 个 U 前方的 R 数量变成 $\lfloor\frac{c(j+1)-b-1}a\rfloor-\lfloor\frac{c-b-1}a\rfloor=\lfloor\frac{cj+(c-b-1\bmod a)}a\rfloor$。 另外,原串最后一段 R 交换后会变成 U,这是不符合要求的,需要将原串结尾一段 R 先提出来,数量为 $n-\lfloor\frac{cm-b-1}a\rfloor$。剩下的部分即 $a'=c,b'=(c-b-1)\bmod a,c'=a,n'=m-1$ 的情况,此处需要特判 $m=0$,于是有式子: $f(a,b,c,n,U,R)=\begin{cases}U^{\lfloor\frac bc\rfloor}f(a\bmod c,b\bmod c,c,n,U,U^{\lfloor\frac ac\rfloor}R)&,a\ge c\wedge b\ge c\\ R^{n}&,m=0\\ R^{\lfloor\frac{c-b-1}a\rfloor}Uf(c,(c-b-1)\bmod a,a,m-1,R,U)R^{n-\lfloor\frac{cm-b-1}a\rfloor}&,\text{otherwise}\end{cases}$ 认为幺半群元素乘积计算是 $\mathcal O(1)$ 的,且过程中全部使用快速幂计算幂次,总复杂度可证明为 $\mathcal O(\log \max(a,c,\frac bc))$。 至于幺半群元素,可以使用矩阵或者贡献值,前者由于冗余元素太多常数过大,一般采用后者。对于本题,矩阵可直接维护 $(1,x,y,y^2,xy,\sum y,\sum y^2,\sum xy)$,要乘上 $8^3$ 的常数,比较爆。更好的做法是维护一段操作序列的贡献,记录 $(x,y,\sum y,\sum y^2,\sum xy)$,式子也比较好推,此处略去。[提交记录](https://www.luogu.com.cn/record/253612902)。