一.斐蜀定理
(1).内容:
若
a,b∈Z 且不全为0,则
∀x,y∈Z,满足
gcd(a,b)∣ax+by,
∃x,y∈Z,使得
ax+by=gcd(a,b)。
(2).推广
1.逆定理
若
a,b∈Z 且不全为0,若
d>0,且
d∣a,d∣b,
∃x,y∈Z,使得
ax+by=d,则
d=gcd(a,b)。
2.扩展
显然可以扩展到多个整数。
(3).进一步结论
对于
a,b∈N,n∈Z且
a⊥b,有以下几个结论:
- 记C=ab−a−b,显然有C为奇数。
- 可得
{t=C,∀x,y∈N,ax+by=tt>C,∃x,y∈N,ax+by=t
- 进而可得:对于方程 ax+by=c,在 [0,C] 中,恰有 2(a−1)(b−1) 个 c 满足条件,即∀n∈N,n,C−n 中有且只一个满足条件。
二.丢番图方程
(1).形态:a1x1b1+...+anxnbn=c,a1...n,b1...n,c∈Z
(2).二元线性丢番图方程:ax+by=c,a,b,c∈Z
1.定理:
对于a,b,c∈Z,∃x,y∈Z,使得ax+by=c⟺gcd(a,b)∣c
2.求解:
a.求出一个解:扩展欧几里得
先求解ax+by=gcd(a,b)
不妨假设a>b,gcd(a,b)=pa+qb
则有
ax+by=gcd(a,b)=gcd(b,amodb)=pb+q(amodb)=qa+(p−q∗⌊ba⌋)b
CPPint extended_gcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int ret,xx=x,yy=y;
ret=extended_gcd(b,a%b,x,y);
x=yy,y=xx-a/b*yy;
return ret;
}
b.所有解
若
x0,y0 为原方程一组解,则有
{x=x0+gcd(a,b)bty=y0−gcd(a,b)at
为原方程一组解,其中t为任意整数
特殊地,我们有最大正整数解和最小正整数解的关系为:
{xmax=ac−ymin∗bymax=bc−xmin∗a
三.线性同余方程
(1).形态:ax≡c(modb)
(2).求解:
显然有ax≡c(modb)⟺ax+by=c
CPPint extended_gcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int ret,tmp;
ret=extended_gcd(b,a%b,x,y);
tmp=x,x=y,y=tmp-a/b*y;
return ret;
}
bool linear_equation(int a,int b,int c,int &x,int &y){
int d=extended_gcd(a,b,x,y);
if(c%d) return 0;
int k=c/d;
x*=k,y*=k;
return 1;
}
四.第一类指数同余方程
(1).形式:ax≡b(modp)
(2).求解
令
x=kt−m,其中
t=⌊p⌋,
0≤m≤t,
1≤k≤⌊tp⌋
则有:
akt−m≡b(modp)
即
aktb−1≡am(modp)
预处理出
a0modp,a1modp,…,atmodp
时间复杂度:
O(p)
五.第二类指数同余方程
(1).形式:xk≡b(modp)
(2).求解:
设
a 是
p 的一个原根,先求出
b≡am(modp)
则
aky≡am(modp)
则
aky−m≡1(modp)
即
ky−m≡0(modp−1)
六.逆元
若
a×x≡1(modb),则
x为
a在
modb意义下的倒数,记作
a−1。
显然有
ba(modb)=a×b−1(modb)
- 扩展欧几里得:
前提:p不一定是质数,a为正整数,a⊥p
同解线性同余方程
CPPint extended_gcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int ret,xx=x,yy=y;
ret=extended_gcd(b,a%b,x,y);
x=yy,y=xx-a/b*yy;
return ret;
}
bool exgcd(int a,int b,int &x,int &y){
int d=extended_gcd(a,b,x,y);
if(1%d) return 0;
int k=1/d;
x*=k,y*=k;
return 1;
}
-
快速幂:
前提:
p为质数,
a为正整数,
a⊥p
根据费马小定理:若
p为质数,
a⊥p,则
ap−1≡1(modp)
则有
axaxx≡1(modp)≡ap−1(modp)≡ap−2(modp)
- 线性算法:
前提:p为质数,i为正整数
显然有
1−1(modp)
不妨设
k为
p/i的商,r为
p/i的余数
∴k∗i+r=p
∴k∗i+r≡0(modp)
同乘
i−1r−1可得:
∴k∗i−1+i−1≡0(modp)
∴i−1≡−k∗r−1(modp)
∴i−1≡−⌊ip⌋∗(pmodi)−1(modp)
CPPinv[1]=1;
for(int i=2;i<p;i++)
inv[i]=(p-p/i)*inv[p%i]%p;
七.原根
模
mod 的原根:
g 是原根当且仅当
g0,g1,…,gp−2 模
mod 两两不同。
- mod=1,2,4,pα,2pα,其中 p 是奇素数,α∈N+
- 原根恰好有 φ(mod−1) 个
- 最小的原根一般不大,可以直接枚举
- g 是原根当且仅当 ∀d∣(mod−1),d=mod−1⟺gd=1
八.二次剩余
勒让德符号:
(pa)=⎩⎨⎧01−1p∣a∃x2≡a(modp)otherwise
欧拉准则:
(pa)≡a2p−1(modp)
二次互反律:对于奇素数
p,q,有
(qp)(pq)=(−1)4(p−1)(q−1)
随机一个
a,使得
a2−n 为非二次剩余,令
w=a2−n
则
x=(a+w)2p+1
CPPLL w,n,p;
struct num{
LL x,y;
num operator *(const num b){
num tmp;
tmp.x=((x*b.x%p+y*b.y%p*w%p)%p+p)%p;
tmp.y=((x*b.y%p+y*b.x%p)%p+p)%p;
return tmp;
}
};
LL qpow(num x,LL y,LL Mod=mod) {
if(y==0) return 1;
num res=x; y--;
for(;y;y>>=1,x=x*x)
if(y&1) res=res*x;
return res.x%Mod;
}
LL cipolla(LL n,LL p){
n%=p;
if(qpow(n,(p-1)/2,p)==p-1) return -1;
LL a;
while(1){
a=(rnd_64()>>1ll)%p;
w=(((a*a)%p-n)%p+p)%p;
if(qpow(w,(p-1)/2,p)==p-1) break;
}
num x={a,1};
return qpow(x,(p+1)/2,p);
}
void solve(){
cin>>n>>p;
if(!n){
cout<<"0\n";
return ;
}
LL ans1=cipolla(n,p),ans2=p-ans1;
if(ans1==-1) cout<<"Hola!\n";
else {
if(ans1==ans2) cout<<ans1<<"\n";
else cout<<min(ans1,ans2)<<" "<<max(ans1,ans2)<<"\n";
}
return ;
}
九.中国剩余定理
(1).内容:
若自然数
m1...r 两两互质,记
M=m1m2...mr
则方程:
⎩⎨⎧x≡a1(modm1)x≡a2(modm2)...x≡ar(modmr)
在modM意义下有唯一解。
(2).过程:
- 计算 ni=miM
- 计算 ni 在 modmi 意义下的逆元 ni−1
- 计算 ci=ni∗ni−1(不对 mi 取模)
- 则方程在 modM 意义下的唯一解为:x=∑i=1raici(modM)
CPPint extended_gcd(__int128 a,__int128 b,__int128 &x,__int128 &y){
if(!b){
x=1,y=0;
return a;
}
__int128 ret,tmp;
ret=extended_gcd(b,a%b,x,y);
tmp=x,x=y,y=tmp-a/b*y;
return ret;
}
signed main(){
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>r;
for1(i,1,r) cin>>m[i]>>a[i],M*=m[i];
for1(i,1,r){
n[i]=M/m[i];
extended_gcd(n[i],m[i],x,y);
c[i]=n[i]*x;
madd(ans,a[i]*c[i],M);
}
cout<<ans;
return 0;
}
(3).扩展中国剩余定理:
若模数不两两互质。
先考虑
x≡a1(modm1),x≡a2(modm2)。
转化成不定方程
x=m1p+q1=m2q+a2
即
m1p−m2q=a2−a1。
若
gcd(m1,m2)∤(a2−a1) 则无解。
否则可以转化成
x≡m1p+a1(modlcm(m1,m2))
CPP__int128 extended_gcd(__int128 a,__int128 b,__int128 &x,__int128 &y){
if(!b){
x=1,y=0;
return a;
}
__int128 ret,tmp;
ret=extended_gcd(b,a%b,x,y);
tmp=x,x=y,y=tmp-a/b*y;
return ret;
}
bool linear_equation(__int128 a,__int128 b,__int128 c,__int128 &x,__int128 &y){
__int128 d=extended_gcd(a,b,x,y);
if(c%d) return 0;
__int128 k=c/d;
x*=k,y*=k;
return 1;
}
void solve(){
cin>>r;
for1(i,1,r) {
rin(m); rin(a);
linear_equation(M,-m,a-A,p,q);
A=M*p+A,M=lcm(M,m);
madd(A,M,M);
}
rout(A);
return ;
}
(4).大部翻倍法
CPPvoid merge(LL &a1,LL &m1,LL a2,LL m2){
if(m1<m2) swap(m1,m2),swap(a1,a2);
while(a1%m2!=a2) a1+=m1;
m1=lcm(m1,m2);
}
void solve(){
cin>>n;
v=0,d=1;
for1(i,1,n){
cin>>a>>m;
a%=m;
merge(v,d,a,m);
}
cout<<v<<"\n";
}
十.积性函数
(1).定义
积性函数:对于函数
f(x),若
∀a,b∈N+,gcd(a,b)=1,f(ab)=f(a)f(b),则称
f(x) 为积性函数。
完全积性函数:对于函数
f(x),若
∀a,b∈N+,f(ab)=f(a)f(b),则称
f(x) 为完全积性函数。
- 常见的积性函数:φ,μ,σ,d
- 常见的完全积性函数:ε,I,id
其中:
ε(n)=[n=1],I(n)=1,id(n)=n
积性函数的性质:
- 设 n=∏piαi,那么 f(n)=∏f(piαi)
- 于是可以用线性筛求出 g(n)=p1α1,然后 f(n)=f(g(n))f(g(n)n),在 O(n) 时间内预处理积性函数的值。
- 若 f(n),g(n) 都是积性函数,那么 fg,f/g 都是积性函数。
(2).欧拉函数 φ
1.定义
若
n=∏i=1spiki,其中
pi 为质数,则
φ(n)=n∏i=1spipi−1,表示小于等于
n 和
n 互质的数的个数$
2.性质:
- 若n为质数,φ(n)=n−1
- 若n为奇数,φ(n)=φ(2n)
- 若a⊥b,φ(ab)=φ(a)φ(b)
- n=∑d∣nφ(d)
- 若n=pk,且p为质数,φ(n)=pk−pk−1
3.求法
a.单个:
CPPint euler_phi(int n){
int ans=n,sq=sqrt(n);
for1(i,2,sq)
if(n%i==0){
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
b.多个:
设p1为n的最小质因子,n′=p1n,显然有φ(p1)=p1−1
若n′modp1=0,φ(n)=p1∗φ(n′)
若n′modp1=0,φ(n)=φ(p1)∗φ(n′)
CPPvoid euler_phi(int n){
phi[1]=1;
for1(i,2,n){
if(!vis[i]) pri.p_b(i),phi[i]=i-1;
for(int j: pri){
if(i>n/j) break;
vis[i*j]=1;
if(i%j==0){
phi[i*j]=phi[i]*j;
break;
}
phi[i*j]=phi[i]*phi[j];
}
}
}
(3).莫比乌斯函数 μ
1.定义
μ(n)=⎩⎨⎧10(−1)kn=1n的质因子最高次数>1n的质因子最高次数=1
2.性质
{10n=1n=1
即
d∣n∑μ(d)=ε(n),μ∗1=ε
3.求法
线性筛:
CPPvoid get_mu(int n){
mu[1]=1;
for1(i,2,n){
if(!vis[i]) pri.p_b(i),mu[i]=-1;
for(int j: pri){
if(i>n/j) break;
vis[i*j]=1;
if(i%j==0){
mu[i*j]=0;
break;
}
mu[i*j]=-mu[i];
}
}
}
(4).约数之和 σ 与 约数个数 d
1.定义
若
n=p1α1×p2α2×…pnαn
则:
d(n)=(1+α1)×(1+α2)×⋯×(1+αn)
σ(n)=(1+p11+p12+⋯+p1α1)×(1+p21+p22+⋯+p2α1)×⋯×(1+pn1+pn2+⋯+pnα1)
=i=1∏n(∑j=0αipij)
=i=1∏n1−pi1−piαi+1
2.求法
- 线性筛求 d
ti 表示 i 的最小质因子的次数,即 min(α1,…,αn)。
CPPvoid make_d(){
t[1]=d[1]=1;
for1(i,2,n){
if(!vis[i]) pri.p_b(i),t[i]=1,d[i]=2;
for(int j: pri){
if(i>n/j) break;
vis[i*j]=1;
if(i%j==0){
t[i*j]=t[i]+1;
d[i*j]=d[i]*(t[i*j]+1)/(t[i]+1);
break;
}
t[i*j]=1;
d[i*j]=d[i]*d[j];
}
}
}
- 线性筛求 σ
ti=min(∑j=0α1p1j,…,∑j=0αnpnj)。
CPPvoid make_sgm(){
sigma[1]=1;
for1(i,2,n){
if(!vis[i]) pri.p_b(i),t[i]=i+1,sigma[i]=i+1;
for(int j: pri){
if(i>n/j) break;
vis[i*j]=1;
if(i%j==0){
t[i*j]=t[i]*j+1;
sigma[i*j]=sigma[i]*t[i*j]/t[i];
break;
}
t[i*j]=j+1;
sigma[i*j]=sigma[i]*sigma[j];
}
}
}
十一.欧拉定理
(1).内容:
若
gcd(a,m)=1,则
aφ(m)≡1(modm)
(2).扩展:
ab≡⎩⎨⎧abmodφ(m),ab,a(bmodφ(m))+φ(m)gcd(a,m)=1gcd(a,m)=1,b<φ(m)gcd(a,m)=1,b≥φ(m)(modm)
十二.威尔逊定理
对于素数
p 有
(p−1)!≡−1(modp)
十三.数论分块
一般用来求形如
∑i=1nf(i)g(⌊in⌋)
若可以
O(1) 计算
f(r)−f(l) 时。
我们考虑将
⌊in⌋ 相同的数放一起计算以使复杂度降至
O(n)
CPPLL H(LL n){
LL ans=0;
for(LL i=1,j;i<=n;i=j+1){
j=n/(n/i);
ans+=(j-i+1)*(n/i);
}
return ans;
}