数论(长期更新)
\(\gcd\) 相关问题
类欧几里得算法
给定\(n,a,b,c\),求\(\sum\limits_{i=0}^n \Big\lfloor \dfrac{ai+b}{c} \Big\rfloor\)和\(\sum\limits_{i=0}^n i\Big\lfloor \dfrac{ai+b}{c} \Big\rfloor\)以及\(\sum\limits_{i=0}^n \Big\lfloor \dfrac{ai+b}{c} \Big\rfloor^2\)
设:
类欧的主要想法就是把式子中的\(a\to a\bmod c\),然后递归下去算。
首先考虑算\(f(a,b,c,n)\)。
当\(a\ge c\)或者\(b\ge c\)时,可以让\(a,b\)对\(c\)取模:
然后只需算\(a<c\)且\(b<c\)的情况,此时我们可以将整个向下取整的式子换掉:
对于后面括号中的式子,进行等价的变形:
那么原来的式子就是:
这样递归即可,这里\(a,c\)位置互换,结合之前的取模,时间复杂度是\(O(\log \max(a,c))\)的。
那么\(f\)就算好了。\(h,g\)几乎一致,但还是有点不同,来推一下:
来算\(g\)。
当\(a\ge c\)或者\(b\ge c\)时:
当\(a<c\)且\(b<c\)时:
为方便,以下令\(m=\Big\lfloor \dfrac{an+b}{c}\Big\rfloor,t=\Big\lfloor \dfrac{cj+c-b-1}{a} \Big\rfloor\)。
\(g\)就算好了,但是发现需要\(h\)。那来算\(h\)。
当\(a\ge c\)或者\(b\ge c\)时:
\( \begin{aligned} h(a,b,c,n)&=\sum\limits_{i=0}^n \Big\lfloor \dfrac{ai+b}{c} \Big\rfloor^2\\ &=\sum\limits_{i=0}^n\Big(\Big\lfloor\dfrac{a}{c}\Big\rfloor i+\Big\lfloor\dfrac{b}{c}\Big\rfloor+\Big\lfloor \dfrac{(a\bmod c)i+b\bmod c}{c} \Big\rfloor\Big)^2\\ &=\sum\limits_{i=0}^n\Big( \Big\lfloor\dfrac{a}{c}\Big\rfloor^2 i^2+\Big\lfloor\dfrac{b}{c}\Big\rfloor^2+\Big\lfloor \dfrac{(a\bmod c)i+b\bmod c}{c} \Big\rfloor^2+2\Big\lfloor\dfrac{a}{c}\Big\rfloor\Big\lfloor\dfrac{b}{c}\Big\rfloor i+2\Big\lfloor\dfrac{a}{c}\Big\rfloor i\Big\lfloor \dfrac{(a\bmod c)i+b\bmod c}{c} \Big\rfloor+2\Big\lfloor\dfrac{b}{c}\Big\rfloor\Big\lfloor \dfrac{(a\bmod c)i+b\bmod c}{c} \Big\rfloor \Big)\\ &=\dfrac{n(n+1)(2n+1)}{6}\Big\lfloor\dfrac{a}{c}\Big\rfloor^2+(n+1)\Big\lfloor\dfrac{b}{c}\Big\rfloor^2+h(a\bmod c,b\bmod c,c,n)+n(n+1)\Big\lfloor\dfrac{a}{c}\Big\rfloor\Big\lfloor\dfrac{b}{c}\Big\rfloor+2\Big\lfloor\dfrac{a}{c}\Big\rfloor g(a\bmod c,b\bmod c,c,n)+2\Big\lfloor\dfrac{b}{c}\Big\rfloor f(a\bmod c,b\bmod c,c,n) \end{aligned} \)
当\(a<c\)且\(b<c\)时:
将\(n^2\)写成\(\Big(2\sum\limits_{i=0}^n i\Big)-n\)的形式:
综上,\(f,g,h\)在计算时相互调用即可,或者使用一个结构体同时算出三者。
边界就是\(n<0\)或者\(a=0\)。
数论分块
用于和式计算中将含有\(\Big\lfloor\dfrac n i\Big\rfloor\)的项在其值相同的时候打包计算。
可以发现\(\Big\lfloor\dfrac n i\Big\rfloor\)的取值只有\(O(\sqrt n)\)种:对于\(1\le i\le \sqrt n\),只有\(\sqrt n\)个\(i\);对于\(\sqrt n<i\le n\),\(\Big\lfloor\dfrac n i\Big\rfloor\)显然至多有\(\sqrt n\)种取值。
主要记忆一些结论:
-
使得\(\lfloor \dfrac ni\rfloor=\lfloor \dfrac nj\rfloor\)成立的最大的\(j=\Big\lfloor \dfrac n{\lfloor \dfrac ni\rfloor}\Big\rfloor\)。\(O(\sqrt n)\)
-
使得\(\lceil \dfrac ni\rceil=\lceil \dfrac nj\rceil\)成立的最大的\(j=\Big\lfloor \dfrac {n-1}{\lfloor \dfrac {n-1}i\rfloor}\Big\rfloor\),注意\(i=n\)时特殊处理,否则分母为\(0\)。\(O(\sqrt n)\)
-
二维/高维形式上,每一维都和一维形式相同,故取\(\min\)即可。
-
使得\(\sqrt{\dfrac np}=\sqrt{\dfrac nq}\)成立的最大的\(q=\Big \lfloor \dfrac{n}{\lfloor\dfrac np\rfloor^2}\Big\rfloor\)
数论函数
积性函数
若对于\(a\perp b\),\(f(ab)=f(a)f(b)\),则称\(f\)是一个积性函数。
若对于任意的\(a,b\),\(f(ab)=f(a)f(b)\),则称\(f\)是一个完全积性函数。
一般来说,对于积性函数\(f(n)\),\(f(1)=1\)。
一些常见的积性函数:
-
单位函数:\(\epsilon(n)=[n=1]\),同时是完全积性。
-
恒等函数:\(\texttt{id}_k(n)=n^k\),同时是完全积性。当\(k=1\)时,简记为\(\texttt{id}(n)=n\)。
-
常数函数:\(1(n)=1\),同时是完全积性。
-
除数函数:\(\sigma_k(n)=\sum\limits_{d|n}d^k\),\(\sigma_0(n)\)即因数个数,简记为\(d(n)\),\(\sigma_1(n)\)即因数之和,简记为\(\sigma(n)\)。
-
欧拉函数。
-
莫比乌斯函数。
积性函数的取值由素数幂处的取值决定,于是求积性函数时总是关注其素数幂处的取值。
狄利克雷卷积(Dirichlet卷积)
称\(h\)是\(f\)和\(g\)的Dirichlet卷积,记作\(h=f\ast g\)。
和狄利克雷生成函数相关,对应生成函数的乘法。
上面的莫比乌斯反演式子就可以写成:\(f=g \ast 1\iff g=f\ast \mu\)
这是由莫比乌斯函数的性质得到的:\(\mu\ast 1=\epsilon\)
欧拉函数的性质可以表示为:\(\varphi \ast 1=\texttt{id}\)
狄利克雷卷积的性质:
-
交换律,\(f\ast g=g\ast f\)。
-
结合律,\(f\ast (g\ast h)=(f\ast g)\ast h\)。
-
分配律,\(f\ast(g+h)=f\ast g+f\ast h\)。
-
等式的性质:\(f=g\iff f\ast h=g\ast h\)。
-
单位元:\(f\ast \epsilon=f\)。
-
逆元:\(f\ast g=\epsilon\),则\(f,g\)互为逆元。逆元是唯一的。
重要结论:
-
两个积性函数的卷积还是积性函数。这个可以证明一坨和式是积性的,然后就可以去筛它。
-
一个积性函数的逆还是积性函数。
点乘
定义点乘\((A\cdot B)(n)=A(n)B(n)\)。
性质:当\(C\)为完全积性函数时,\((A\cdot C)\ast (B\cdot C)=(A\ast B)\cdot C\)。即此时点乘对狄雷克利卷积有分配律。
\(C=\texttt{id}_k\)很常见。
常用的一些东西:
-
\((\mu\cdot \texttt{id}_k)\ast \texttt{id}_k=(\mu\cdot \texttt{id}_k)\ast(1\cdot \texttt{id}_k)=(\mu\ast 1)\cdot \texttt{id}_k=\epsilon \cdot \texttt{id}_k=\epsilon\)
-
\((\varphi\cdot \texttt{id}_k)\ast \texttt{id}_k=(\varphi\cdot \texttt{id}_k)\ast(1\cdot \texttt{id}_k)=(\varphi\ast 1)\cdot \texttt{id}_k=\texttt{id}_{k+1}\)
可以发现两个积性函数的点乘还是积性函数。
欧拉函数
\(\varphi(n)\)定义为\(\le n\)的正整数中有多少个与\(n\)互质。
运用下面的\(\mu\)的性质,可以化简定义式:
由两个积性函数的狄利克雷卷积还是积性函数,可知\(\varphi\)的积性。
来看其素数幂处的取值,设\(p\in\texttt{Prime}\),则\(\varphi(p)=p-1,\varphi(p^k)=p^k-p^{k-1}\)。
那么可以得到单点求\(\varphi(n)\)的式子,以下设\(n=\prod\limits_{i\ge 1,p_i\in\texttt{Prime}}p_i^{k_i}\):
还有常用的性质:\(n=\sum\limits_{d|n}\varphi(d)\)。
直接用\(\mu\ast \texttt{id}=\varphi\)两边卷上\(1\)即可得到。可以用于替换一坨式子,或许可以称之欧拉反演(?
莫比乌斯函数
初始化时记得\(\mu(1)=1\)。
莫比乌斯反演
性质:
证明一下:
显然\(\sum\limits_{d\mid n}\mu(d)=\sum\limits_{d\mid n'}\mu(d)\),其中设\(n=\prod\limits_{1\le k\le x} p_k^{a_k}\),那么\(n'=\prod\limits_{1\le k\le x} p_k\)。
于是结合定义,原式即\(\sum\limits_{0\le k\le x} (-1)^k\binom xk=[x=0]=[n=1]=\epsilon(n)\)。
反演式子:\(f(n)=\sum\limits_{d|n} g(d)\iff g(n)=\sum\limits_{d|n}\mu(d)f(\dfrac{n}{d})\)
筛法
埃氏筛
考虑筛素数。一个方法是从\(2\)开始,把一个数字的所有倍数都划去,剩下的数就是素数了。\(O(n\log\log n)\)
线性筛(欧拉筛)
埃氏筛还是太慢,关注其过程,发现一个数会被它的每个质因子都标记一次。
我们优化这一点,让一个数只会被它的最小质因子标记。
这样是\(O(n)\)的。
实现是为人所熟知的。
实现
void init(){
np[0]=np[1]=true;
for(int i=2;i<=lim;++i){
if(!np[i]) p.emplace_back(i);
for(int j=0;j<(int)p.size()&&p[j]*i<=lim;++j){
np[i*p[j]]=true;
if(i%p[j]==0) break;
}
}
}
注意到在线性筛的过程中,我们也得到了一个数\(i\)的最小质因子。
筛积性函数
对于当前枚举的素数\(p\)和合数(也可能是质数,但是这里当做合数)\(i\),我们只需考虑两种情况。
-
\(i\perp p\),那么由积性函数性质,\(f(ip)=f(i)f(p)\)。这里的\(f(i)\)和\(f(p)\)都是已经算过的。
-
\(p|i\),那么这时\(p\)是\(i\)的最小质因子,这里就要特殊考虑转移了,需要一些精细的观察。
-
特别地,当筛出了一个素数\(p\)时,\(f(p)\)的取值要特殊算。
还有一种对注意力要求不是很高的方法:
我们设\(n=\prod_{i=1}^mp_i^{\alpha_i}\),\(g(n)=p_1^{\alpha_1}\)。
那么\(g(n)\)是可以在线性筛过程中轻松算出来的。
\(f(n)=f\Big(\dfrac{n}{g(n)}\Big)f\Big(g(n)\Big)\)。注意特判\(g(n)=n\)的情况。
这里要求对于任意素数\(p\),能够快速求出\(f(p^k)\)。
杜教筛
这里不需要积性的良好性质。
对于任意数论函数\(f(n)\),求\(S(n)=\sum\limits_{i=1}^nf(i)\)。
先找到另一个数论函数\(g(n)\),设\(f\ast g=h\),先来看\(h\)的前缀和:
把右边第一项拿出来,得到\(g(1)S(n)=\sum\limits_{i=1}^nh(i)-\sum\limits_{d=2}^ng(d)S(\lfloor\frac{n}{d}\rfloor)\),注意右侧下标从\(2\)开始。
如果\(g,h\)的前缀和好求,那么右边就可以整除分块做了。但是直接做是\(O(n^{\frac{3}{4}})\)的。通过分析复杂度加均值不等式,可以得到用线性筛预处理前\(m=n^{\frac{2}{3}}\)个\(S(i)\)时,复杂度为\(O(n^{\frac{2}{3}})\)。
PN筛
Powerful Number
设正整数\(n=\prod\limits_{i=1}^mp_i^{k_i}\),如果对于每一个\(1\le i\le m\),\(k_i>1\),则称\(n\)是一个Powerful Number。
性质:
首先,每一个PN都可以表示为\(a^2b^3\)的形式。这是显然的,考虑每一个指数,如果它是偶数,全部扔到\(a^2\)中,否则拿出\(3\)次扔到\(b\)中,剩下的扔到\(a^2\)中。
然后,我们可以证明\(n\)以内的PN有\(O(\sqrt n)\)个。先枚举\(a\),然后看合法的\(b\)有多少个。\(\int_1^{\sqrt n}\sqrt[3]{\dfrac{n}{x^2}}\mathrm d x=O(\sqrt n)\)。
如何求\(n\)以内的所有PN呢?线性筛出\(\sqrt n\)以内的所有素数,然后DFS各素数的指数即可。\(O(\sqrt n)\)。
Powerful Number筛
即PN筛。
需要积性。
求特定积性函数前缀和:\(S(n)=\sum\limits_{i=1}^nf(i)\)。
PN筛要求存在一个函数\(g\)满足:
-
\(g\)是积性函数。
-
\(g\)的前缀和容易求。
-
在质数\(p\)处,\(g(p)=f(p)\)。
假设现在已经找到了\(g\),我们设\(G(n)=\sum\limits_{i=1}^ng(i)\)。
我们又构造\(h\)使得\(g\ast h=f\),由狄雷克利卷积的性质可知\(h\)的积性,于是\(h(1)=1\)。
在素数\(p\)处,\(f(p)=g(p)h(1)+g(1)h(p)=g(p)\),于是\(h(p)=0\)。
根据\(h\)的积性以及\(h(p)=0\),可知\(h\)只在PN或者\(1\)处取得非零值。这里注意\(h(1)=1\)。
根据\(f=g\ast h\),可以来求\(S(n)\):
以上注意\(d=1\)时也要计算值。
现在枚举\(d\)是\(O(\sqrt n)\)的。要计算\(h(d)\),考虑利用它的积性,只需计算出\(h(p^c)\)处的取值即可(\(c>1\))。
算\(h(p^c)\)的方法有两种:
-
直接推式子找到\(h\)的通项。
-
递推一下,根据\(f=g\ast h\)可得\(f(p^c)=\sum\limits_{i=0}^cg(p^i)h(p^{c-i})\),提出第一项就有\(h(p^c)=f(p^c)-\sum\limits_{i=1}^cg(p^i)h(p^{c-i})\)。
复杂度\(O(\sqrt n\log n)\),而且很松。
费马小定理
若\(p\)为素数,\(\gcd(a,p)=1\),则\(a^{p-1}\equiv 1\pmod p\)
证明不会。
于是当\((a,p)=1\)时,\(a^x\bmod p=a^{x\bmod (p-1)}\bmod p\)。
欧拉定理
若 \(\gcd(a,m)=1\) ,则 \(a^{\varphi(m)} \equiv 1 \pmod m\)
扩展欧拉定理
乘法逆元
乘法逆元的\(n\)种求法。
\(ax\equiv 1\pmod p\)
-
扩欧:要求\(\gcd(a,b)=1\)。
-
费马小定理:要求\(p\)是素数且\(\gcd(a,p)=1\)。
-
线性求逆元:
首先,显然\(1^{-1}\equiv 1\pmod p\)。
我们希望求\(i^{-1}\),考虑\(p=ki+j(0\le j<i)\),则\(ki+j\equiv 0\pmod p\)。
两侧同乘\(i^{-1}j^{-1}\),则\(kj^{-1}+i^{-1}\equiv 0\pmod p\),即\(i^{-1}\equiv -kj^{-1}\pmod p\)。
由于负数不太好,再加上\(pj^{-1}\),则\(i^{-1}\equiv (p-k)j^{-1}\pmod p\)
- 求任意\(n\)个数的逆元:求出前缀积的逆元,再倒着推回去求每个前缀积的逆元,那么每个数的逆元都可以\(O(1)\)计算。
同余基本性质
应该都知道吧。
中国剩余定理
求解一元线性同余方程组。
一般的CRT
强调\(m_1,\dots ,m_n\)互质。
过程:
-
求\(M=\prod m_i\)。
-
对于第\(i\)个方程,求\(p_i=\dfrac{M}{m_i}\)以及\(p_ip_i^{-1}\equiv 1\pmod {m_i}\)
-
\(x=\sum a_ip_ip_i^{-1} \bmod M\)
可以证明这样是对的。
扩展中国剩余定理(exCRT)
考虑合并两个方程\(x\equiv a_1\pmod{m_1}\)与\(x\equiv a_2\pmod{m_2}\)。
于是用exgcd求出\((\lambda_1,\lambda_2)\)或者报告无解。
然后得到通解形式\(x=x_0+lcm(m_1,m_2)\),这个容易验证是对的。
于是合并得到了\(x\equiv x_0\pmod{lcm(m_1,m_2)}\)。
两两合并\(n\)次就解出来了。
Lucas定理和exLucas
Lucas
强调模数\(p\)为质数。
证:
注意到 \({p \choose n} \equiv [n=p \lor n=0] \pmod p\),
因此 \((a+b)^p \equiv a^p+b^p \pmod p\)。
对于 \(f(x)=(1+x)^n\),\([x^m]f(x)={n \choose m}\)。
我们现在对 \(f(x)\) 做一点变换,
\[\begin{aligned} f(x)&=(1+x)^n\\ &=(1+x)^{p \times \lfloor \frac{n}{p} \rfloor}(1+x)^{n \bmod p}\\ &=((1+x)^{p})^{\lfloor \frac{n}{p} \rfloor}(1+x)^{n \bmod p} \end{aligned} \]所以 \(f(x) \equiv (1+x^p)^{\lfloor \frac{n}{p} \rfloor} (1+x)^{n \bmod p} \pmod p\)
设 \(h(x)=(1+x^p)^{\lfloor \frac{n}{p} \rfloor},g(x)=(1+x)^{n \bmod p}\),
则 \([x^m]f(x) \equiv [x^{kp}]h(x) \times [x^r]g(x) \pmod p\)。
因为 \(0 \le r < p\),所以将 \(m\) 拆成 \(m=kp+r\) 的形式的方法是唯一的,即 \(k=\lfloor \frac{m}{p} \rfloor,r=m \bmod p\)。
所以 \([x^{kp}]h(x)={\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{m}{p} \rfloor},[x^r]g(x)={n \bmod p \choose m \bmod p}\)。
原式得证。
感觉不是很严谨,感性理解一下。
exLucas
和上方的Lucas定理相比,除了用途,其余并无关系。
求解:
其中\(M\)为合数。
首先我们可以对\(M\)唯一分解,\(M=\prod\limits_{i\ge 1} p_i^{k_i}\)。
然后使用CRT把原问题拆了:求出\(\dbinom nm\bmod p^k\),然后可以合并出原问题的答案。
把\(\dbinom nm\)写成阶乘形式,\(\dbinom nm=\dfrac{n!}{m!(n-m)!}\)。
现在还求不了逆元,因为分母可能不与\(p^k\)互质。所以直接把阶乘中所有\(p\)因子给提出来。
记\(v_p(n)\)表示\(n!\)中\(p\)因子的个数,这个是很容易递归求的,\(v_p(n)=v_p(\lfloor \frac{n}{p} \rfloor)+\lfloor \frac{n}{p} \rfloor\)。
于是现在就是要求\(\dfrac{\dfrac{n!}{p^{v_p(n)}}}{\dfrac{m!}{p^{v_p(m)}}\cdot \dfrac{(n-m)!}{p^{v_p(n-m)}}}\times p^{v_p(n)-v_p(m)-v_p(n-m)}\bmod p^k\)
分母上的数现在可以求逆元了,那么现在要求的就是\(\dfrac{n!}{p^{v_p(n)}}\bmod p^k\)
考虑把\(n!\)拆一下,将每个\(p\)的倍数都拆出来一个\(p\)因子,可以得到\(n!=\Big(\Big\lfloor\frac{n}{p} \Big\rfloor\Big)!\times p^{\lfloor \frac{n}{p}\rfloor}\times \prod\limits_{p\not\mid i,i=1}^n i\)
再把两边都除以\(v_p(n)\),得到\(\dfrac{n!}{p^{v_p(n)}}=\dfrac{\Big(\Big\lfloor\frac{n}{p} \Big\rfloor\Big)!}{p^{v_p(\Big\lfloor\frac{n}{p} \Big\rfloor)}}\times \prod\limits_{p\not\mid i,i=1}^n i\)
右边前面那一坨显然是可以递归下去做的。
后面那一坨我们再拆一下。由于\(\bmod p^k\),那么肯定有长为\(p^k\)的循环节,于是\(\prod\limits_{p\not\mid i,i=1}^n i=\Big(\prod\limits_{p\not\mid i,i=1}^{p^k} i\Big)^{\Big\lfloor\frac{n}{p^k} \Big\rfloor}\times \prod\limits_{p\not\mid i,i=1}^{n\bmod p^k} i\)。
前后两坨都可以\(O(p^k)\)算出来,前面可以套个快速幂。或者由Wilson定理,前面括号内的东西\(\bmod p^k\)只会是\(\pm 1\),于是关注一下指数的奇偶就行。
这样递归下去算,时间复杂度单次询问\(O(p\log p)\)。或许可以预处理一些东西做到更好的复杂度。
原根
需要了解一些性质。
阶
对于\(a\in\mathrm N,m\in\mathrm N_+,(a,m)=1\),满足\(a^n\equiv 1\pmod m\)的最小的\(n\)称为\(a\)模\(m\)的阶,记作\(\delta_m(a)\)或者\(\text{ord}_m(a)\)。
原根的定义
设\(m\in \mathrm N_+,g\in\mathrm Z\),若\((g,m)=1\),且\(\delta_m(g)=\varphi(m)\),则称\(g\)为模\(m\)的原根。
原根判定定理
设\(m\ge 3,(g,m)=1\),则\(g\)是模\(m\)的原根的充要条件是:对于\(\varphi(m)\)的每一个素因子\(p\),都有\(g^{\frac{\varphi(m)}{p}}\not\equiv 1\pmod m\)。
原根存在定理
一个数\(m\)存在原根当且仅当:\(m=2,4,p^\alpha,2p^\alpha\),其中\(p\)是奇素数,\(\alpha\in\mathrm N_+\)。
离散对数
主要用大步小步。
BSGS
求解\(a^x\equiv b\pmod m\),其中\(a\perp m,0\le x<m\)。注意\(m\)不一定是素数。
我们可以设\(x=A\sqrt m-B\),那么上式就是\(a^{A\sqrt m}\equiv b\times a^B\pmod m\)。
其中\(1\le A,B\le \sqrt m\)。
我们已知\(a,b\),可以先枚举\(B\)算出右边的所有取值,存到Hash表中,然后枚举\(A\)算左边的取值,在Hash表中查找。
从而我们可以得到所有的\(x=A\sqrt m-B\)。
这里要求\(a\perp m\)是为了等式两边可以同时除以\(a^B\)。
\(O(\sqrt m)\)。
进阶应用
求解\(x^a\equiv b\pmod p\)。
可以转化为BSGS。
exBSGS
剩余
主要用二次剩余。
定义:令\(a\perp p\),若存在\(x\in \mathbb Z\)使得\(x^2\equiv a\pmod p\),则称\(a\)为模\(p\)的二次剩余,否则称\(a\)为模\(p\)的二次非剩余。
\(p=2\)时是简单的,这里只讨论\(p\)为奇素数的情况。
Euler判别法
对于奇素数\(p\)和\(a\perp p\),
二次剩余的数量
在模奇素数\(p\)的意义下,二次剩余和二次非剩余都有\(\dfrac{p-1}{2}\)个。
Lengendre符号
性质:
对于任意整数\(a\),
使用原根可以证明。
Cipolla算法
求解\(x^2\equiv n\pmod p\)。
我们先找一个\(a\),使得\(a^2-n\)是二次非剩余。由于二次非剩余占了一半,所以这是容易得到的。
根据上面的性质,\((a^2-n)^{\frac{p-1}{2}}\equiv -1\pmod p\)。
我们在模\(p\)意义下定义一个虚数单位\(i^2\equiv (a^2-n)\),将所有虚数表示为\(A+Bi\),并认为虚数取模就是\(A,B\)分别取模。
Lemma 1:
证明:\(i^p=i(i^2)^{\frac{p-1}{2}}\equiv (a^2-n)^{\frac{p-1}{2}}i\equiv -i\pmod p\)。
Lemma 2:
证明:用二项式定理展开即可。
我们可以进行计算了:
于是得到一个解为\((a+i)^{\frac{p+1}{2}}\)。可以通过反证法得到这个解总是为实数。
设存在复数\(A+Bi(B\ne 0)\)满足\((A+Bi)^2\equiv n\pmod p\),那么就有\(A^2+B^2(a^2-n)-n\equiv -2ABi\pmod p\)。
左边是实数,那么右边必为实数,于是\(A=0\),所以\((Bi)^2\equiv n\pmod p\),即\(i^2\equiv nB^{-2}\pmod p\)。左边是二次非剩余,右边是二次剩余,于是矛盾。得证。
代码实现需要一个手写复数类。
代码
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
int rd(){
int f=1,r=0;
char ch=gc();
while(!isdigit(ch)){ if(ch=='-') f=-1;ch=gc();}
while(isdigit(ch)){ r=(r<<1)+(r<<3)+(ch^48);ch=gc();}
return f*r;
}
mt19937 rnd(233);
int mo,i_2;
inline int add(int x,int y){
return x+y>=mo?x+y-mo:x+y;
}
inline int sub(int x,int y){
return x-y<0?x-y+mo:x-y;
}
inline int mul(int x,int y){
return 1ll*x*y%mo;
}
struct cpl{
int re,im;
cpl(int _x=0,int _y=0):re(_x),im(_y){}
cpl operator*(const cpl &tmp){
return cpl(add(mul(re,tmp.re),mul(mul(im,tmp.im),i_2)),add(mul(re,tmp.im),mul(im,tmp.re)));
}
};
int ksm(int x,int y){
int rs=1;
while(y){
if(y&1) rs=mul(rs,x);
x=mul(x,x);
y>>=1;
}
return rs;
}
cpl ksm(cpl x,int y){
cpl rs(1,0);
while(y){
if(y&1) rs=rs*x;
x=x*x;
y>>=1;
}
return rs;
}
bool lengendre(int x){
return ksm(x,(mo-1)>>1)==1;
}
int cipolla(int n,int p){
n%=p,mo=p;
if(!n) return 0;
if(!lengendre(n)) return -1;
int a=rnd()%mo;
while(lengendre(sub(mul(a,a),n))) a=rnd()%mo;
i_2=sub(mul(a,a),n);
return ksm(cpl(a,1),(mo+1)>>1).re;
}
int T,n,p;
void solve(){
n=rd(),p=rd();
int rs=cipolla(n,p);
if(!rs) puts("0");
else if(rs==-1) puts("Hola!");
else{
if(rs>p-rs) rs=p-rs;
printf("%d %d\n",rs,p-rs);
}
}
int main(){
T=rd();
while(T--) solve();
return 0;
}
素数
定义都知道。
素数有无限个。欧拉有一个巧妙的证明。
素数定理
设\(\pi(x)\)表示\(\le x\)的数中素数的个数。
那么\(\pi(x)\sim \dfrac{x}{\ln x}\)。\(\dfrac{x}{\ln x}\)是下界。\(\pi(x)\)略大一些。
哥德巴赫猜想
猜想:任意\(\ge 4\)的偶数,都可以表示为两个质数的和。
这个在很大的范围内都是对的,但是还没有证明。
Bertrand 假设(Bertrand-Chebyshev Theorem)
对于任意 \(n\in \mathrm N_+\),\(\exists p\in [n,2n] \ s.t. \ p\in \text{Prime}\)。
推论:
-
对于任意 \(n>6\),\(\exists p_1,p_2\in [n,2n] \ s.t. \ p_1,p_2\in \text{Prime}\land p_1=4k_1+1\land p_2=4k_2+3\)。
-
对于任意 \(k\in \mathrm N\),\(\exists B\in \mathrm N \ s.t. \ \forall n>B,\text{至少存在} k \text{个素数} p\in [n,2n]\)。
构造题中出现了。CF2089A。
Miller-Rabin素性测试和Pollard Rho分解质因数算法
这是唯一真史
Miller-Rabin 可以在 \(O(k\log n)\) 的复杂度内对 \(n\) 做 \(k\) 轮测试以判断其是否为质数。是一个概率性的测试,拿着必要条件当充分条件用。
二次探测定理
对于
Stern-Brocot Tree和法里级数
Stern-Brocot树
可以构造满足\(m\perp n\)的所有非负分数\(\frac{m}{n}\)的集合。
我们从初始的两个分数\((\dfrac{0}{1},\dfrac{1}{0})\)出发,不断进行以下操作:
新的分数\(\dfrac{m+m'}{n+n'}\)称为\(\dfrac{m}{n}\)和\(\dfrac{m'}{n'}\)的中位分数。
这样可以用一个三元组来描述一个位置:\((\dfrac{m}{n},\dfrac{m+m'}{n+n'},\dfrac{m'}{n'})\)。
这些分数的阵列可以看成是一棵无限的二叉树构造。\((\dfrac{m}{n},\dfrac{m+m'}{n+n'},\dfrac{m'}{n'})\)的左儿子是\((\dfrac{m}{n},\dfrac{2m+m'}{2n+n'},\dfrac{m+m'}{n+n'})\),右儿子是\((\dfrac{m+m'}{n+n'},\dfrac{m+2m'}{n+2n'},\dfrac{m'}{n'})\)。
它的顶端看起来像是这样:
来看它的性质。最重要的一个是:如果\(\dfrac{m}{n}\)和\(\dfrac{m'}{n'}\)是这个构造中任意一个阶段的相邻分数,我们就有\(m'n-mn'=1\)。
我们来归纳证明它。初始状态\((\dfrac{0}{1},\dfrac{1}{0})\)是符合的。
当插入一个中位分数时,我们要验证的就是:
这里打开括号后是与原来的条件等价的。于是这个性质总是成立。
有这个东西后由裴蜀定理的逆定理,我们就知道了Stern-Brocot树中的分数总是最简的。
此外,设\(0\le \dfrac{m}{n}<\dfrac{m'}{n'}\),容易证明\(\dfrac{m}{n}<\dfrac{m+m'}{n+n'}<\dfrac{m'}{n'}\)。
这就说明了Stern-Brocot树不会重复。
下面说明不会遗漏任意一个非负分数。
考虑\(\dfrac{a}{b}\),首先有\(\dfrac{m}{n}<\dfrac{a}{b}<\dfrac{m'}{n'}\)。
我们每次生成一个中间分数\(\dfrac{m}{n}<\dfrac{m+m'}{n+n'}<\dfrac{m'}{n'}\),从而可以类似二分的找下去。这个过程不可能无限进行,因为条件
蕴含
从而
我们把左边打开就得到了\(am'n-bmn'+bm'n-amn'=a(m'n-mn')+b(m'n-mn')=a+b\ge m'+n'+m+n\)。
右边在不断增大,左侧不变,于是在至多\(a+b\)步后我们可以得到\(\dfrac{a}{b}\)。
我们可以用矩阵描述在Stern-Brocot树上的行动。
设当前点为\(\dfrac{m+m'}{n+n'}\),我们把它的两个祖先放到矩阵中,但是要注意上下颠倒一下,表示为\(\begin{bmatrix}n & n'\\m & m'\end{bmatrix}\)。
颠倒是为了初始时更加符合直觉:\(I=\begin{bmatrix}1 & 0\\ 0 & 1\end{bmatrix}\)
设当前点的矩阵为\(M\),我们用\(ML\)表示向左边走一步得到的矩阵,\(MR\)表示向右边走一步得到的矩阵。
那么可以得到\(L=\begin{bmatrix}1 & 1\\0 & 1\end{bmatrix},R=\begin{bmatrix}1 & 0\\ 1 & 1\end{bmatrix}\)
设\(f(S)\)表示经过\(S\)中的依次移动走到的分数对应的矩阵,那么有\(f(S)=S\)
我们还可以观察到,Stern-Brocot树是一棵二叉搜索树,于是我们可以在它上面进行二叉搜索。
以上二者结合,有两种二叉搜索的方式来确定\(\dfrac{m}{n}\)在Stern-Brocot树中的位置:
-
从\(I\)开始移动。
-
从\(\dfrac{m}{n}\)开始移动回到\(I\)。
我们还可以发现,移动过程中可能会连续进行很多次\(L\)或者\(R\),我们可以二分长度,一整段\(L\)或者\(R\)一起跳过。
复杂度是\(\log^2(m+n)\)的,这是因为“拐弯”的位置只会有\(\log(m+n)\)个,一次拐弯后分子分母都会变成原来的两倍,所以得证。
这样就可以快速二分了。
法里级数
阶为\(N\)的法里级数记作\(\mathcal F_N\),它是介于\(0\)和\(1\)之间的分母不超过\(N\)的所有最简分数组成的集合,而且按照递增的次序排列。
这是Stern-Brocot树的一个子树。
很牛,但是整棵Stern-Brocot树还是更有意义。