数论入门2
另一种类型的数论...
GCD,LCM
定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有:
将a和b分解质因数为\(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}\),那么\(gcd(a,b)=\prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=\prod_{i=1}^{n}pi^{max(ai,bi)}\)(0和任何数的最大公约数是这个数,最小公倍数是0)
显然成立的吧。
所以我们有\(gcd(a,b)*lcm(a,b)=ab\)。
求\(gcd(a,b)\)的方法:
首先我们有:\(gcd(a,b)=gcd(b,a-b)(a>=b)\)
显然的啊,两个数相减怎么可能影响他们的最大公约数,毕竟是“公”约数,相减肯定还存在这个因子啊。
所以拓展一下我们就有:\(gcd(a,b)=gcd(b,a \% b)(a>=b)\)
取模就是不断相减,所以也是成立的呀。
所以我们可以写出简洁的代码:
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
很显然这个复杂度是log的,每次至少减少一半。
lcm的话,\(a/gcd(a,b)*b\)即可。
然后呢,gcd和lcm具有交换律和结合律:
\(gcd(a,b,c)=gcd(gcd(a,b),c)=gcd(c,b,a)\)
所以求多个数的gcd或lcm的时候就可以递推求啦。
还有一个东西就是\(gcd(ka,kb)=k*gcd(a,b)\),也是显然的。
exGCD
对于方程\(ax+by=c\),显然若\(gcd(a,b)|c\)的时候才有解。
因为不整除的话\(ax+by\)肯定有\(c\)不包含的因子,那样的话怎么可能有解呢?
然后呢,我们可以通过这样的方式快速借助求gcd的过程求出\(ax+by=gcd(a,b)\)的一组解。
当\(a=gcd(a,b),b=0\)时,显然\(x=1,y=0\)。
令\(a = b, b = a \% b\),则有方程\(b *x1 +(a \% b) * y1 = gcd(b, a \% b)\)
又因为\(gcd(a, b) = gcd(b, a \% b)\),且\(a \% b = a - b * ?a / b?\)
则\(b * x1 + (a - b * ?a / b?) * y1 =gcd(a, b)\)
整理得:\(a * y1 +b * (x1 - ?a / b? *y1) = gcd(a, b)\)
所以原方程中:\(x = y1, y = x1 - ?a / b? *y1\)。于是我们只要递归求出\(x1, y1\)就能求出\(x, y\)。
我们现在已经求得了\(ax +by = gcd(a, b)\)的解,那么对于方程\(ax + by = c (gcd(a, b) | c)\)呢?
因为已经知道\(a *x1 +b * y1 = gcd(a, b)\)的解\(x1, y1\),左右两边同乘以\(c / gcd(a, b)\) 得:
\(a * x1 * c / gcd(a, b) +b * y1 * c / gcd(a, b) = c\)
则原方程的一组解\(,x2 = x1 * c / gcd(a, b), y2 = y1 * c / gcd(a, b)\)
由此得出解集\(,{(x, y) | x = x2 + k * b / gcd(a, b), y = y2 - k * a / gcd(a, b), k ∈ Z}\)
对于线性同余方程\(ax\equiv c\quad(mod\quad b)\),我们怎么做呢?
显然可以转化成\(ax+by=c\)的形式,然后直接用扩欧解决啦。
贴个代码:
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1;y=0;return a;}
ll g=exgcd(b,a%b,y,x);y-=a/b*x;
return g;
}
欧拉定理
费马小定理:
若p是质数,且\(gcd(a,p)=1\),则\(a^{p-1}\equiv1(mod\quad p)\)。
欧拉定理:
若\(gcd(a,p)=1\),则\(a^{\varphi(p)}\equiv1(nod \quad p)\)。
扩展欧拉定理:
\(a^b\equiv \begin{cases} a^{b\%\varphi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~~gcd(a,p)\neq1,b<\varphi(p)\\ a^{b\%\varphi(p)+\varphi(p)}~~~~gcd(a,p)\neq1,b\geq\varphi(p) \end{cases}~~~~~~~(mod~p)\)
\(\varphi\)为欧拉函数。
有个作用就是在算\(a^b\)的时候对b进行取模,使运算更高效,具体见luogu欧拉定理模板题
乘法逆元
若\(gcd(a,b)=1,\)\(ax\equiv 1(mod~p)\),则称x为a在模p意义下的乘法逆元。
那么求法就很显然了。
欧拉定理:a在模p意义下的逆元为\(a^{\varphi(p)-1}\)。
exGCD:当做一个同余方程求,但是要通过+kp的方式变为一个正数。
此外还有一个线性求逆元的算法。
首先,1在任何模数下的逆元都是1。
然后设\(p=i*k+r,r<i,1<i<p\)。
那么我们有\(i*k+r\equiv 0(mod~p)\)
两边同时乘上\(i^{-1}*r^{-1}\)得:
\(k*r^{-1}+i^{-1}\equiv 0(mod~p)\)
\(i^{-1}\equiv -k* r^{-1}(mod~p)\)
因为\(k=\lfloor p/i\rfloor,r=p\%i\),所以我们得到了逆元的递推式:
a[i]=-(p/i)*a[p%i]%p;
以及提一句,逆元是完全积性函数,从定义式里面就能看出来。
对于一个前缀积的序列的话,我们可以求出最后一项的逆元,然后\(O(n)\)递推回去,实际上逆元可以理解为模意义下的\(\frac{1}{x}\),怎么递推的话也很显然了,以阶乘为例:
fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;
ifa[n]=ksm(fac[n],P-2);
for(int i=n-1;~i;i--) ifa[i]=ifa[i+1]*(i+1)%P;
还有就是:
\((a/b)\%p=(a\%(bp))/ p\)
证明:
\((a/b)\%p=a/b-?(a/b)/p?*p\)
\(=a/b-?a/(b*p)?*p\)
\(=a/b-?a/(bp)?*b*p/b\)
\(=(a\%(bp) )/p\)
CRT
已知系数全部为1的线性同余方程组:
\(x \equiv a_i(mod ~p_i)\),其中\(p_i\)两两互质,求x的最小非负整数解。
那么我们考虑这样一个思路:
从1到n考虑每个同余方程组,我们设\(M=\prod_{i=1}^{n}p_i\),那么当我们考虑到第i个方程的时候,我们设\(T=\frac{M}{p_i}\),那么我们发现把第i个方程的解\(x\)加上\(kT\)的话,\(x+kT\)带到别的同余方程组的余数不会改变。
假设我们已经求出了前\(i-1\)个方程的通解\(x\),求出了第\(i\)个方程的一个解\(x_i\),那么显然,\(Tx_i+x\)是前\(i\)个方程的解。
我们用exGCD求出第i个线性同余方程组\(Tx_i\equiv a_i(mod~p_i)\)的解,一步步合并即可,因为\(p_i\)显然和\(T\)互质,所以实际上是求出逆元之后乘上\(a_i\)。
exCRT
已知系数全部为1的线性同余方程组:
\(x \equiv a_i(mod ~p_i)\),其中\(p_i\)都是正整数,求x的最小非负整数解。
上面的算法失效了。为什么?都不一定互质了怎么可能还去求逆元?
所以我们要考虑一个新的思路:
假设我们已经求出了前\(i-1\)个方程的通解\(x\),设\(M\)为前i-1个数的lcm,那么我们发现\(x+kM\)如果能够满足第\(i\)个方程,那么前i个方程就都解出来啦。
我们写个式子:\(x+kM \equiv a_i(mod~p_i)\),移项得\(kM \equiv a_i-x(mod ~p_i)\)。
那么我们解出来k之后,前i个方程的通解就出来啦,一步步做下去即可。
贴个代码:
ll mul(ll x,ll y,ll p){ll g=0;for(;y;y>>=1,x=(x+x)%p) if(y&1) g=(g+x)%p;return g;}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1;y=0;return a;}
ll g=exgcd(b,a%b,y,x);y-=a/b*x;
return g;
}
for(int i=1;i<=n;i++) scanf("%lld%lld",&b[i],&a[i]);
ans=a[1];M=b[1];
for(int i=2;i<=n;i++)
{
ll A=M,B=b[i],c=(a[i]%B-ans%B+B)%B,x,y;
ll gcd=exgcd(A,B,x,y),d=B/gcd;
if(c%gcd) return 0;x=mul(x,c/gcd,d);
ans+=x*M;M*=d;ans=(ans%M+M)%M;
}
注意一下,因为是求lcm,所以那个B要除以gcd。
BSGS
exBSGS
原根
Lucas
exLucas
Miller-Rabin
Pollard-Rho
原文地址:https://www.cnblogs.com/CK6100LGEV2/p/10352130.html