整除与同余
整除和同余理论
同余方程
定义:形如 \(ax \equiv c\ (\text{mod}\ b) \Longleftrightarrow ax+by=c\) 的方程。
裴蜀定理
内容:若 \(a,b\) 为正整数,则 \(ax+by=c\) 有整数解当且仅当 \(\gcd(a,b)\) 为 \(c\) 的因数。
exgcd(扩展欧几里得算法)
扩展欧几里得算法(exgcd)——可求解 \(\gcd\),解同余方程、乘法逆元。
内容:对于形如 \(ax+by=\gcd(a,b)\) 的方程,当 \(b=0\) 时,\(x=1,y=0\) 是方程的一组特解。
模板
inline int exgcd(int a,int b,int &x,int &y)
{
int d=a;
if(b==0) x=1,y=0;
else d=exgcd(b,a%b,y,x),y-=(a/b)*x;
return d;
}
乘法逆元
定义:若 \(ax \equiv 1(\text{mod }p)\),就称 \(a\) 与 \(x\) 在模 \(p\) 意义下互为乘法逆元。
例:
若要求 \((\dfrac{m}{n})\text{ mod }p\),则转化为 \((m\times inv_n)\text{ mod }p\),其中 \(inv_n\) 表示模 \(p\) 意义下 \(n\) 的逆元。
标准分解式
定义:将质因数分解的结果,按照质因数大小,由小到大排列,并将相同质因数的连乘积,以指数形式表示。
例:
\(2020\) 的标准分解式为 \(2^2 \times 55\times 101\)。
欧拉函数
定义:\(\varphi(n)\) 指在小于 \(n\) 的正整数中与 \(n\) 互质的数的个数。
求法:
1.先化为标准分解式:
2.再根据公式计算:
但当 \(m\) 为合数时,且不知道 \(m\) 的因数分解式时,通常很难求出 \(n\) 的欧拉函数值 \(\varphi(m)\)。
欧拉函数线性筛法,时间复杂度 \(O(n)\)
模板
const int MAXN=4e4+5;
int phi[MAXN],prime[MAXN],m,ans;
bool vis[MAXN];
inline void getphi()
{
phi[1]=1;
for(int i=2;i<=MAXN;i++)
{
if(!vis[i])
prime[++m]=i,phi[i]=i-1;
for(int j=1;j<=m;j++)
{
if(i*prime[j]>MAXN) break;
vis[i*prime[j]]=true;
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
欧拉定理
内容:对于两个正整数 \(a,n\),若 \(a,n\) 互质,则
一般常用到它的推论:对于两个正整数 \(a,n\),若 \(a,n\) 互质,则
利用这个推论,在满足 \(a,m\) 互质的前提下,即使 \(b\) 较大,我们也可以轻松地计算 \(a^b\text{ mod }m\) 的值。
扩展欧拉定理
通常用来解决欧拉定理的推论中 \(a,m\) 不互质时的情况。
内容:
费马小定理
定义:设 \(p\) 是一个素数,则对于任意整数 \(a\),有
同样可以用来求逆元。
威尔逊定理
定义:对于一个素数 \(p\),有
BSGS(大步小步算法)
通常用来求解离散对数问题,即求解形如 \(a^x \equiv b\ (\text{mod }p)\) 的方程的解。
内容:
取 \(k=\lceil\sqrt{p}\rceil\),令 \(x=ky+z\),则
预处理出所有 \(\dfrac{b}{a^z}\) 并哈希存储,枚举 \(y\) 后判断是否有满足条件的即可。
模板
inline int BSGS(int a,int b,int MOD)
{
map<int,int>ma;
int cur=1,t=sqrt(MOD)+1;
for(int i=1;i<=t;i++)
{
cur=cur*a%MOD;
ma[b*cur%MOD]=i;
}
int now=cur;
for(int i=1;i<=t;i++)
{
if(ma[now]) return i*t-ma[now];
now=now*cur%MOD;
}
return -1;
}
CRT(中国剩余定理)
通常用来求解形如
的同余方程的解,其中 \(p_1,p_2,...,p_n\) 均为质数。
内容:
设 \(M=\prod p_i,m_i=\dfrac{M}{p_i},t_i\equiv \dfrac{1}{m_i}\ (\text{mod }p)_i\)
那么我们可以发现 \(a_it_im_i\equiv 0\ (\text{mod }m_i),a_it_im_i\equiv a_i\ (\text{mod }p_i)\)
于是答案便为 \(\sum a_it_im_i\ (\text{mod }M)\)
有时需要用到龟乘。
模板
inline int exgcd(int a,int b,int &x,int &y)
{
int d=a;
if(b==0) x=1,y=0;
else d=exgcd(b,a%b,y,x),y-=(a/b)*x;
return d;
}
int a[MAXN],b[MAXN],n;
inline int CRT(int mod)
{
int ans=0;
for(int i=1;i<=n;i++)
{
int M=mod/a[i];
int x,y;
int d=exgcd(M,a[i],x,y);
ans=((ans+x*M*b[i])%mod+mod)%mod;
}
return ans;
}
exCRT(扩展中国剩余定理)
内容:
对于上面的方程,假设合并两个方程:
那么合并出来的模数一定是 \(\text{lcm}(p_1,p_2)\)。
于是有:\(x=k_1p_1+a_1=k_2p_2+a_2\).
用 \(\text{exgcd}\) 求出 \(k_1,k_2\) 即可。
其中无解的情况就是 \(\text{exgcd}\) 无解的情况。
模板
int n,a[MAXN],b[MAXN];
inline int exgcd(int a,int b,int &x,int &y)
{
int d=a;
if(b==0) x=1,y=0;
else d=exgcd(b,a%b,y,x),y-=(a/b)*x;
return d;
}
inline int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
inline int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
inline int Mod(int x,int p)
{
return (x%p+p)%p;
}
int x0,y0;
inline int exCRT(int A,int B)
{
for(int i=2;i<=n;i++)
{
int g=Mod(b[i]-B,a[i]),d=exgcd(A,a[i],x0,y0);
if(g%d) printf("No Solution\n");
x0*=g/d,x0%=a[i]/d;
B+=A*x0,A=lcm(A,a[i]),B=Mod(B,A);
}
return B;
}