数论的同余分支
我的同余,就像筛子,全是漏洞。
本文如果不特殊说明,出现的字母均属于 \(\mathbb{N}_+\) 集合。
一些概念
按照从易到难的顺序。
整除与同余。
设 \(a,b(a\ne 0)\),如果 \(\exist c\),使得 \(ac=b\),则称 \(b\) 整除 \(a\),或 \(a\) 是 \(b\) 的因数,\(b\) 是 \(a\) 的倍数,记作 \(a|b\)。如果 \(b\) 不整除 \(a\),则记作 \(a\nmid b\)。
设 \(m,a,b\),如果 \(m|(a-b)\),则称 \(a,b\) 在模 \(m\) 意义下同余,记作 \(a\equiv b\pmod{m}\)。不妨令 \(a>b\),则上式等价于 \(\exist c\),使得 \(b+cm=a\)。
完全剩余系。
定义 \(m\) 的完全剩余系是一个集合,集合内是所有模 \(m\) 可能得到的值,一般来说为:
逆元。
定义 \(a\) 在模 \(m\) 下的逆元为 \(a^{-1}\),满足 \(a^{-1}a\equiv1\pmod{m}\)。\(a^{-1}\) 存在,当且仅当 \(a,m\) 互质。
最大公因数与最小公倍数。
设 \(a,b\),则称最大的 \(c\) 满足 \(c|a,c|b\) 为 \(a,b\) 的最大公因数,记作 \(\gcd(a,b)\)。特别地,如果 \(\gcd(a,b)=1\),则称 \(a,b\) 互质。
设 \(a,b\),则称最小的 \(c\) 满足 \(a|c,b|c\) 为 \(a,b\) 的最小公倍数,记作 \(\operatorname{lcm}(a,b)\)。
容易发现 \(\operatorname{lcm}(a,b)=\frac{ab}{\gcd(a,b)}\)。
质数与合数。
对于数 \(p(p\ge 2)\),如果 \(\forall 1\le i<p\),均有 \(i\) 与 \(p\) 互质,则称 \(p\) 为质数,否则 \(p\) 为合数。\(1\) 不是质数也不是合数。本文约定 \(\mathbb{P}\) 为质数集合。
算术基本定理。
对于数 \(n\),它存在,且唯一存在一个质数分解:
阶与原根。
对于数 \(a,m\),定义 \(a\) 模 \(m\) 的阶为最小的数 \(c\),满足 \(a^c\equiv1\pmod{m}\),通常记为 \(\delta_m(a)\)。
对于数 \(m\),定义模 \(m\) 的原根为数 \(g\),当且仅当 \(\delta_m(g)=\varphi(m)\),原根存在,当且仅当 \(m\) 能被表示为 \(2,4,p^c,2p^c\) 的其中一种形式,其中 \(p\) 为奇质数。
欧几里得算法
欧几里得算法是一种快速求 \(\gcd\) 的算法,它基于以下恒等式:
其中边界条件为 \(\gcd(a,0)=a\)。递归实现的时间复杂度是 \(\mathcal{O}(\log a)\) 的,注意到每次递归要么交换 \(a,b\),要么 \(a\) 至少缩小一倍。
考虑这样一个不定方程,其中未知数是 \(x,y\):
注意到 \(\gcd(b,a\bmod{b})=\gcd(a,b)\),所以我们考虑令 \(a'=b,b'=a\bmod{b}\),然后递归计算下列方程的解 \(x',y'\):
边界条件是当 \(b'=0\) 时,\(x'=1,y'=0\)。考虑如何通过 \(x',y'\) 得到 \(x,y\)。代入 \(a,b\):
注意到 \(a\bmod{b}=a-\lfloor\frac{a}{b}\rfloor b\),则:
所以可以得到:
递归下去即可得到原方程的解。时间复杂度依然是欧几里得算法的 \(\mathcal{O}(\log a)\),这个算法一般被称为扩展欧几里得算法,或者 \(\rm exgcd\)。
注意到这个不定方程相当于:
所以 \(\rm exgcd\) 也可以用来解形如上式的线性同余方程。
刚刚讨论的是一些特殊的不定方程和同余方程,现在我们来看看一般的情况,下文以不定方程为例。考虑:
根据裴蜀定理,上式有解,当且仅当 \(\gcd(a,b)|m\)。判掉这种情况后,我们令 \(d=\frac{m}{\gcd(a,b)}\)。则我们求出方程 \(ax'+by'=\gcd(a,b)\) 的解后,上式的解即为:
证明只需令关于 \(x',y'\) 的方程两边同时乘 \(d\)。
刚刚求出的是一组特解,那我们想要所有解怎么办呢?考虑设 \(q\in\mathbb{Q}\),则显然有:
成立。我们只需保证 \(qb,qa\in\mathbb{Z}\) 即可找到一组解。
给出 \(x,y,m,n,L\),求方程 \(x+mt\equiv y+nt\pmod{L}\) 的最小正整数解 \(t\),或报告无解。(\(1\le x\ne y,n,m\le 2\times 10^9,1\le L\le 2.1\times 10^9\))
考虑把上式化成线性同余方程的形式即:
注意我们上文的推导是基于 \(a\ge0\) 的,所以如果本题中 \(m-n<0\),需要给等式两边变号。
之后求出一组特解即可。时间复杂度 \(\mathcal{O}(\log n)\)。注意处理负数。
欧拉定理
欧拉定理的内容为:
由此可以推出扩展欧拉定理,可以对指数取模:
其中后两个等式对于 \(m\) 无要求。
给出一个长为 \(n\) 的序列 \(a\),常数 \(c\),和 \(m\) 次操作,操作分两种:
- 将区间 \(l,r\) 内的数 \(a_i\) 替换为 \(c^{a_i}\)。
- 求 \(\sum\limits_{i=l}^r a_i\pmod{p}\)。
(\(1\le n,m\le 5\times 10^4,1\le p\le 10^8,0<c<p,0\le a_i<p\))
注意到操作一定次数后,一个位置的值会变为:
的指数塔形式,而我们要求的是它模 \(p\) 的值,考虑用扩欧给质数取模:
而里面又是一次递归的过程。注意到 \(\varphi(p)\) 每次要么把奇质数变偶数,要么把合数缩小至少两倍,所以在 \(\mathcal{O}(\log p)\) 次数后,\(\varphi(\varphi(\varphi(\cdots(p))))\) 会变为 \(1\),而那时不管还剩啥,得到的值均为 \(0\),指数塔就停下了。而注意到,一旦指数塔的层数高于这个层数,则 \(a_i\) 就会因为模 \(1\) 而被舍去,再对它进行操作就不会改变它在模 \(p\) 意义下的值了。
所以注意到,我们可以用类似吉司机线段树的思想,维护每个区间内层数的最小值,如果层数最小值都比最大层数高了,就不再计算这个区间,否则暴力递归下去计算。根据势能分析,单次操作是均摊 \(\mathcal{O}(\log p)\) 的。暴力计算某个位置 \(c^{a_i}\) 的值可以在预处理出 \(\varphi\) 后直接递归计算。算上快速幂的复杂度是 \(\mathcal{O}(\sqrt{p}\log p+m\log^3p+n\log n)\) 的,看起来不好通过。加上光速幂后即可做到 \(\mathcal{O}((\sqrt{p}+\sqrt{m})\log p+m\log^2p+n\log n)\),足以通过。
中国剩余定理
中国剩余定理,又称 \(\rm CRT\),可以快速求解线性同余方程组,即形如:
其中 \(\forall i\ne j\),都有 \(\gcd(p_i,p_j)=1\)。
算法流程如下:
- 令 \(P=\prod\limits_{i=1}^n p_i\)。
- 对于第 \(i\) 个方程:
- 令 \(p'_i=\frac{P}{p_i}\)。
- 计算 \(p_i'\) 在模 \(p_i\) 意义下的逆元 \(p_i'^{-1}\)
- 计算 \(c_i=p_i'p_i'^{-1}\pmod{P}\)。
- 则最终唯一解为 \(\sum\limits_{i=1}^n a_ic_i\pmod{P}\)
证明不会,自行搜索。
给出 \(g,n\),求:
\[g^{\sum\limits_{k|n}\binom{n}{k}}\pmod{999,911,659} \](\(1\le g,n\le 10^9\))
首先特判掉 \(g\equiv0\pmod{999,911,659}\) 的情况。然后考虑用欧拉定理,把指数取个模,原式即为:
所以现在的问题为求:
发现枚举 \(n\) 的因数,复杂度是可以接受的,问题在于求出组合数。因为模数不是质数,所以无法预处理阶乘及其逆元。但我们注意到:
而这四个都是质数,考虑分别求出上式在模这些质数意义下的值 \(a_1,a_2,a_3,a_4\)。则现在我们相当于求解:
只需要上 \(\rm CRT\) 即可求出 \(x\) 在模 \(999,911,658\) 意义下的值。而 \(a\) 的求解可以直接上 \(\rm Lucas\) 定理。时间复杂度 \(\mathcal{O}(d(n)\log p)\)。
但有些时候,线性同余方程组的模数不互质,这时普通的 \(\rm CRT\) 就不够用了,我们需要 \(\rm exCRT\)。先考虑两个方程的情况:
则考虑返璞归真,把它们化成不定方程的形式:
两式相减:
注意到这就是 \(\rm exgcd\) 能解的方程了。如果该方程无解,则同余方程无解。否则求出 \(u,v\) 后,原同余方程的解即为:
而我们发现,上述求解的过程为方程合并的过程,所以对于多个方程的情况,我们依然可以用上述做法,两两合并得到最终的解。
题意太长了,不说,与本文无关的贪心和特判也不说了。我们需要求解的是这样一个线性同余方程组:
考虑对于每个方程用 \(\rm exgcd\) 分别求出一组解 \(x=b_i\pmod{m_i}\),然后再用 \(\rm exCRT\) 两两合并即可得到最后的解。注意计算过程时可能爆 long long
即可。时间复杂度 \(\mathcal{O}(n\log n)\)。
Lucas 定理
\(\rm Lucas\) 定理是计算组合数模小质数 \(p\) 的值的,它把组合数的上下指标在 \(p\) 进制下进行了分解,具体来讲有:
其中第二项可以预处理阶乘直接计算,前一项可以递归计算。时间复杂度 \(\mathcal{O}(p+\log n)\)。
但这要求模数为质数,如果模数不为质数,我们可以使用 \(\rm exLucas\) 定理。
考虑把模数分解质因数,则我们可以只求解组合数模 \(p^c\) 意义下的值,然后用 \(\rm CRT\) 合并即可。
现在的问题变为:
考虑把组合数拆成阶乘:
注意到现在我们的问题卡在分母不一定与 \(p^c\) 互质,无法求出逆元。考虑把分子分母中 \(p\) 提取出来有:
这样就可以求逆元了。现在我们的问题又变为:
其中 \(x\) 表示 \(n!\) 中 \(p\) 的次数。考虑把 \(1\sim n\) 中所有 \(p\) 的倍数提出来:
可以通过手玩一组的方式感性理解。注意到提取出来的并不是全部的次数,\(\left(\frac{n}{p}\right)!\) 中可能还有,所以考虑等式两边同时除以剩下的次数,即可得到一个递归式:
此时 \(x\) 已经能求了,递归下去即可:
然后我们来考虑 \(\frac{n!}{p^x}\)。注意到 \(p^c\) 的范围不会很大,所以 \(p^x\) 的范围也不大,后面两个 \(\prod\) 可以直接求。则接下来又是递归的问题。
分别求出 \(x,y,z\) 和 \(\frac{n!}{p^x},\frac{m!}{p^y},\frac{(n-m)!}{p^z}\) 后,直接求个乘法逆元即可得到模 \(p^c\) 意义下组合数的值,最后用 \(\rm CRT\) 组合即可得到模原模数意义下的值。
BSGS
\(\rm BSGS\) 算法通常用于求解离散对数的问题,即求解以下同余方程的解 \(x\):
考虑将 \(x\) 分块,即令 \(x=A\lceil\sqrt{p}\rceil-B(A,B\le \lceil\sqrt{p}\rceil)\),则原方程即:
注意这里用到了 \(a\bot p\) 的条件把 \(a^{-B}\) 乘到了右边。考虑枚举 \(B\),并把 \(ba^B\pmod{p}\) 的值存在哈希表内。然后枚举 \(A\),在哈希表内查询 \(a^{A\lceil\sqrt{p}\rceil}\) 对应的 \(B\),如果有,就找到了一组解 \(A\lceil\sqrt{p}\rceil-B\)。时间复杂度 \(\mathcal{O}(\sqrt{p}+\log p)\)。
但还是老问题,如果 \(\gcd(a,p)>1\) 呢?这时就有 \(\rm exBSGS\) 算法。设 \(d=\gcd(a,p)\),当 \(d\nmid b\) 时,原方程无解,否则原方程显然可以化为:
此时如果有 \(\gcd(\frac{p}{d},a)=1\),则就可以用 \(\rm BSGS\) 直接求 \(x-1\) 的值了。否则我们就继续除 \(\gcd(\frac{p}{d},a)\) 的值直到互质。但注意到,假如除了 \(k\) 次,我们得到的解只能是大于 \(k\) 的解。注意到 \(k\) 是 \(\mathcal{O}(\log p)\) 级别的,我们先提前枚举小于等于 \(k\) 的值是否合法即可。时间复杂度 \(\mathcal{O}(\sqrt{p}+\log p)\)。
例题和要用下面的阶与原根,所以在下面放了。
阶与原根相关
阶与原根的定义上面已经说了,这里只说一些性质和用法。
- \(a^1,a^2,\cdots,a^{\delta_m(a)}\) 两两模 \(m\) 不同余。
- \(a^n\equiv 1\pmod{m}\iff\delta_m(a) | n\),由此还能推出 \(a^p\equiv a^q\pmod{m}\iff p\equiv q\pmod{\delta_m(a)}\)。
- \(\delta_m(ab)=\delta_m(a)\delta_m(b)\iff\gcd(\delta_m(a),\delta_m(b))=1(a\bot m,b\bot m)\)。
- \(\delta_m(a^k)=\dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)}\)。
- 当 \(m\ge 3\) 时,\(g\) 是 \(m\) 的原根,当且仅当 \(\gcd(g,m)=1\),且对于 \(\varphi(m)\) 的所有质因数 \(p\),都有 \(a^{\frac{\varphi(m)}{p}}\not\equiv 1\pmod{m}\)。
- 如果 \(m\) 有原根,则原根个数为 \(\varphi(\varphi(m))\) 个。如果设 \(g\) 为最小原根,则 \(g^k(k\bot\varphi(m))\pmod{m}\) 均为原根。
- 对于所有的 \(t\bot m\),总存在一个 \(c\),满足 \(g^c\equiv t\pmod{m}\)。
- \(m\) 的最小原根的数量级是 \(\mathcal{O}(m^{0.25})\) 级别的。
这样求最小原根我们可以枚举。求阶的话,注意到根据欧拉定理 \(a^{\varphi(m)}\equiv 1\pmod{m}\),枚举 \(\varphi(m)\) 的因数即可得到阶。
\(T\) 组询问,每次询问 \(n\) 的所有原根。(\(1\le T\le 10,2\le n\le 10^6\))
首先我们可以枚举求出最小原根 \(g\),这部分的时间复杂度是 \(\mathcal{O}(n^{0.25}d(n))\)。(还要算上枚举因数判断的复杂度)然后枚举 \(k(k\bot \varphi(n),k\le \varphi(n))\) 的值计算所有原根即可。总时间复杂度 \(\mathcal{O}(n^{0.25}d(n)+n)\)。
CF1106F Lunar New Year and a Recursive Sequence
定义无穷正整数序列 \(f_1,f_2,\cdots\),对于任意的 \(i>k\),\(f_i\) 是如下递归定义的:
\[f_i=\prod_{j=1}^k f_{i-j}^{b_j}\bmod{p} \]其中 \(p=998,244,353\)。给出序列 \(b_1,b_2,\cdots,b_k\),已知 \(f_1=f_2=\cdots=f_{k-1}=1,f_n=m\),求 \(f_k\) 可能的值,或报告无解。(\(1\le k\le 100,1\le b_i,m<p,k<n\le 10^9\),你需要保证 \(1\le f_k<p\))
发现 \(\prod\) 和乘方这种东西非常不好处理,但这个形式和常系数齐次递推确实很像。说明这道题可能要求我们把 \(\prod\) 变为 \(\sum\),乘方变为乘法,这样就能凑成常系数齐次递推的形式。
考虑在实数意义下,这种事非常好办,直接取对数即可。而在模意义下,我们可以取离散对数。具体来讲,我们想找到一个 \(c\),满足存在一个 \(l\),使得:
则 \(a\) 的离散对数就可以定义为 \(l\)。发现关键在于 \(c\) 的选择,合适的 \(c\) 应该让尽可能多的数拥有离散对数。注意到原根的性质有一条:
对于所有的 \(t(t\bot p)\),在模 \(p\) 意义下都能被 \(p\) 的原根 \(g\) 的幂次的形式表示。
又因为此题 \(p\) 是质数,所以我们只需选择它的原根 \(3\) 作为 \(c\),即可保证所有的正整数都存在离散对数。而求离散对数的过程相当于求解这样一个同余方程:
可以用 \(\rm BSGS\) 在 \(\mathcal{O}(\sqrt{p})\) 的时间复杂度内轻松实现。但需要注意,求解的 \(x\) 和离散对数是模 \(\varphi(p)\) 同余的。
设 \(f_i\) 的离散对数为 \(lf_i\),则上式可以化为:
发现可以用矩阵乘法表示这个过程,即:
如果设转移矩阵为 \(\mathbf{A}\),则整个过程相当于:
观察到 \(1\) 的离散对数是 \(0\) 即可得到初始矩阵。注意到我们只关心 \(lf_n\) 的值,所以根据上面的等式,我们可以得到如下同余式:
由于矩阵是已知的,所以不妨把 \((\mathbf{A}^{n-k})_{k,k}\) 设为一个常量 \(a\),再把 \(lf_k\) 设为 \(x\),\(lf_n\) 设为 \(b\),则我们现在只需要解一个线性同余方程就够了:
可以用 \(\rm exgcd\) 轻松判无解和求出通解。求出 \(x\) 后,\(f_k\) 即为 \(g^x\bmod{p}\)。时间复杂度 \(\mathcal{O}(k^3\log n+\sqrt{p})\)。计算的时候注意模数在这一步到底是 \(p\) 还是 \(\varphi(p)\)。
根据这道题,我们考虑这样的同余方程:
则其实根据原根的知识我们知道,可以令 \(x=g^c\),则:
\(g^a\) 是已知的,这样就成功化为 \(\rm BSGS\) 的形式。求出 \(c\) 后,解即为 \(g^c\)。
而一个数的离散对数的求法在题解中已经说的比较清楚了,不再赘述。
- 序列
题面不放了,是权限题。
发现指数非常难处理,所以考虑取离散对数。具体来讲,如果模数 \(p\) 存在原根 \(g\),则对于 \(x\),满足 \(x\bot p\),定义 \(x\) 的离散对数为 \(\ln x\),满足:
我们可以在求出原根 \(g\) 后,用 \(\rm BSGS\) 求出模 \(p-1\) 意义下的 \(\ln x\),即求出下列同余方程的解 \(a\):
则有 \(a\equiv \ln x\pmod{p-1}\)。
考虑设 \(y=\ln x\),则定义新的序列 \(y_i\) 满足:
即 \(y_i=m^{i-1}y\)。原问题相当于找到最小的 \(i\),满足存在一个 \(j(j>i)\),使得:
这相当于:
考虑枚举 \(i\)。如果 \(y\bot p-1,m\bot p-1\),则上式容易化简成:
求最小的 \(j-i\) 就相当于求 \(\delta_{p-1}(m)\),即模 \(p-1\) 意义下 \(m\) 的阶。这个容易通过枚举 \(\varphi(p-1)\) 的约数得到,根据的引理是:
然后我们考虑 \(\gcd(y,m)>1\) 的情况,注意到这种情况下就不能同时约去 \(y\) 了。考虑设 \(d=\gcd(y,m)\),则可以得到:
此时,如果 \(m\bot \frac{p-1}{d}\),则我们就又能套用上面的做法求出 \(j-i\)。
然后考虑当此时依然有 \(\gcd(m,\frac{p-1}{d})>1\) 时,当前 \(i\) 就不在循环节内了,因为我们无论如何都找不到阶了。所以我们考虑给 \(i\) 加一,继续这个过程,即令 \(m\leftarrow m^2\)。
现在考虑枚举 \(i\) 的过程,这个过程会不会很慢?考虑每次都会把 \(p-1\) 至少缩小两倍,当缩小到 \(1\) 时,无论如何都会停下这个过程,所以 \(i\) 移动次数只有 \(\mathcal{O}(\log p)\) 级别。
总结一下,我们先 \(\mathcal{O}(p^{0.25}d(p))\) 求出原根,然后 \(\mathcal{O}(p^{0.5})\) 求离散对数。之后枚举 \(i\),然后每次求 \(\gcd\),最后求一次阶即可得出答案,时间复杂度 \(\mathcal{O}(\log^2 p+d(p))\)。总时间复杂度 \(\mathcal{O}(T(p^{0.25}d(p)+p^{0.5}+\log^2p))\)。