数论基础知识
1. 质数
质数:在大于1的整数中,只包含1和它本身这两个约数的数。
n
n
n中最多只包含一个大于
s
q
r
t
(
n
)
sqrt(n)
sqrt(n)的质因子。
1.1 质数的判定
试除法 O ( s q r t ( n ) ) O( sqrt(n) ) O(sqrt(n))
bool isPrime(int n)
{
if(n<2) return false;
for(int i=2;i<=n/i;i++)
if(n%i==0)
return false;
return true;
}
1.2 分解质因数
试除法 O ( l o g ( n ) ) O( log(n) ) O(log(n))~ O ( s q r t ( n ) ) O( sqrt (n) ) O(sqrt(n))
void divide(int n)
{
for(int i=2;i<=n/i;i++)
if(n%i==0)//i一定是质数
{
int s=0;
while(n%i==0)
{
n/=i;
s++;
}
printf("%d^%d",i,s);
if(n!=1) printf(" * ");
}
if(n>1) printf("%d^%d\n",n,1);
}
1.3 筛质数
1.3.1 朴素筛法
int prime[N],pNum;
bool p[N];
void find_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(!p[i])
{
prime[pNum++]=i;
for(int j=i+i;j<=n;j+=i)
p[j]=true;
}
}
}
1.3.2 线性筛(欧拉筛)
int prime[N],pNum;
bool p[N];
void find_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(!p[i])
prime[pNum++]=i;
for(int j=0;prime[j]<=n/i;j++)//从小到大枚举最小质数
{
p[prime[j]*i]=true;
if(i%prime[j]==0) break;//prime[j]一定是i的最小质因子
}
}
}
2. 约数
2.1 试除法求所有约数
vector<int> get_divisors(int n)
{
vector<int> res;
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
res.push_back(i);
if(i!=n/i) res.push_back(n/i);
}
}
sort(res.begin(),res.end());
return res;
}
int main()
{
int n;cin>>n;
auto res=get_divisors(n);
for(auto t:res) printf("%d ",t);
}
2.2 约数个数
对 N N N质因数分解
N N N= p 1 α 1 p_1^{α_1} p1α1 p 2 α 2 p_2^{α_2} p2α2 p 3 α 3 p_3^{α_3} p3α3… p n α n p_n^{α_n} pnαn
其中 p p p为质数,1~ N N N对 p i p_i pi的倍数有 p i 0 p_i^{0} pi0, p i 1 p_i^{1} pi1… p i α i p_i^{α_i} piαi
约数个数=( α 1 α_1 α1+1)( α 2 α_2 α2+1)( α 3 α_3 α3+1)…( α n α_n αn+1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
int n;cin>>n;
unordered_map<int,int> primes;
for(int i=2;i<=n/i;i++)
{
while(n%i==0)
{
n/=i;primes[i]++;
}
}
if(n>1) primes[n]++;
ll res=1;
for(auto prime:primes)
res=res*(prime.second+1)%mod;
printf("%lld\n",res);
return 0;
}
2.3 约数之和
约数之和= ( p 1 0 p_1^{0} p10+ p 1 1 p_1^{1} p11+ p 1 2 p_1^{2} p12… p 1 α 1 p_1^{α_1} p1α1)( p 2 0 p_2^{0} p20+ p 2 1 p_2^{1} p21+ p 2 2 p_2^{2} p22… p 2 α 1 p_2^{α_1} p2α1) …( p n 0 p_n^{0} pn0+ p n 1 p_n^{1} pn1+ p n 2 p_n^{2} pn2… p n α n p_n^{α_n} pnαn)
t t t=1
t
t
t=
p
1
p_1
p1+1
…
t
t
t=
p
1
p_1
p1*(
p
1
α
1
−
2
p_1^{α_1-2}
p1α1−2+…+
p
1
0
p_1^{0}
p10 )+1
t t t= p 1 p_1 p1* ( p 1 p_1 p1*( p 1 α 1 − 2 p_1^{α_1-2} p1α1−2+…+ p 1 0 p_1^{0} p10 )+1 ) +1
t t t= p 1 α 1 p_1^{α_1} p1α1+…+ p 1 2 p_1^{2} p12+ p 1 1 p_1^{1} p11+ p 1 0 p_1^{0} p10
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
int n;cin>>n;
unordered_map<int,int> primes;
for(int i=2;i<=n/i;i++)
{
while(n%i==0)
{
n/=i;primes[i]++;
}
}
if(n>1) primes[n]++;
ll res=1;
for(auto prime:primes)
{
int p=prime.first,a=prime.second;
ll t=1;
while(a--) t=(t*p+1)%mod;
res=res*t%mod;
}
printf("%lld\n",res);
return 0;
}
2.4 最大公约数(欧几里得算法)
d d d可以整数 a a a, d d d可以整数 b b b,那么 d d d可以整数 a ∗ x + b ∗ y a*x+b*y a∗x+b∗y
0除以任何一个数都等于0,所以任何数都可以整除0
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
2.5 最小公倍数
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
3. 欧拉函数
3.1 定义
定义 1~
N
N
N中与
N
N
N互质的数的个数被称为欧拉函数
N=
p
1
α
1
p_1^{α_1}
p1α1
p
2
α
2
p_2^{α_2}
p2α2 ···
p
k
α
k
p_k^{α_k}
pkαk
Φ ( N ) \Phi (N) Φ(N)=N(1- 1 p 1 \frac{1}{p_1} p11)(1- 1 p 2 \frac{1}{p_2} p21)···(1- 1 p k \frac{1}{p_k} pk1)
3.2 证明
3.2.1 证明
根据容斥原理
Φ
(
N
)
\Phi(N)
Φ(N)=
N
N
N
-
N
p
1
\frac{N}{p_1}
p1N -
N
p
2
\frac{N}{p_2}
p2N -···-
N
p
k
\frac{N}{p_k}
pkN
+
N
p
1
∗
p
2
\frac{N}{p_1*p_2}
p1∗p2N+
N
p
1
∗
p
3
\frac{N}{p_1*p_3}
p1∗p3N +···+
N
p
k
−
1
∗
p
k
\frac{N}{p_{k-1}*p_{k}}
pk−1∗pkN
-
N
p
1
∗
p
2
∗
p
3
\frac{N}{p_1*p_2*p_3}
p1∗p2∗p3N -
N
p
1
∗
p
2
∗
p
4
\frac{N}{p_1*p_2*p_4}
p1∗p2∗p4N -···-
N
p
k
−
2
∗
p
k
−
1
∗
p
k
\frac{N}{p_{k-2}*p_{k-1}*p_{k}}
pk−2∗pk−1∗pkN
+
N
p
1
∗
p
2
∗
p
3
∗
p
4
\frac{N}{p_1*p_2*p_3*p_4}
p1∗p2∗p3∗p4N+
N
p
1
∗
p
2
∗
p
3
∗
p
5
\frac{N}{p_1*p_2*p_3*p_5}
p1∗p2∗p3∗p5N+···
N
p
k
−
3
∗
p
k
−
2
∗
p
k
−
1
∗
p
k
\frac{N}{p_{k-3}*p_{k-2}*p_{k-1}*p_k}
pk−3∗pk−2∗pk−1∗pkN
3.2.2代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int res=n;
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
res=res/i*(i-1);//(a-1)/a
while(n%i==0) n/=i;
}
if(n>1) res=res/n*(n-1);
}
cout<<res<<endl;
return 0;
}
3.3筛法求欧拉函数
3.3.1推导
(1)
i
i
i为质数,
ϕ
(
i
)
\phi ( i )
ϕ(i)=
i
i
i - 1
(2)
i
i
i
m
o
d
mod
mod
p
j
p_j
pj
=
=
0
==0
==0 时,
ϕ
(
p
j
∗
i
)
\phi( p_j * i )
ϕ(pj∗i) =
p
j
p_j
pj *
ϕ
(
i
)
\phi( i )
ϕ(i)
(3)
i
i
i
m
o
d
mod
mod
p
j
p_j
pj
!
=
0
!= 0
!=0 时,
ϕ
(
p
j
∗
i
)
\phi(p_j * i)
ϕ(pj∗i)=
ϕ
(
p
j
)
\phi (p_j)
ϕ(pj) *
ϕ
(
i
)
\phi( i )
ϕ(i) =
ϕ
(
i
)
\phi ( i )
ϕ(i) * (
p
j
p_j
pj-1)
3.3.2代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int primes[N],cnt;
int phi[N];
bool p[N];
ll get_eulers(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!p[i])
{
primes[cnt++]=i;
phi[i]=i-1;
}
for(int j=0;primes[j]<=n/i;j++)
{
p[primes[j]*i]=true;
if(i%primes[j]==0)
{
phi[primes[j]*i]=phi[i]*primes[j];
break;
}
phi[primes[j]*i]=phi[i]*(primes[j]-1);
}
}
ll res=0;
for(int i=1;i<=n;i++) res+=phi[i];
return res;
}
int main()
{
int n;cin>>n;
cout<<get_eulers(n)<<endl;
}
4.欧拉定理
4.1 定理
欧拉定理(Euler Theorem,也称费马-欧拉定理或欧拉函数定理):
设
a
,
m
a,m
a,m
∈
∈
∈
N
+
N^{+}
N+,且
g
c
d
(
a
,
m
)
=
=
1
gcd (a,m) == 1
gcd(a,m)==1,我们有
a
ϕ
(
m
)
a^{\phi(m)}
aϕ(m)
≡
1
≡1
≡1
(
m
o
d
(mod
(mod
m
m
m)
4.2 证明
a
,
n
a ,n
a,n互质
1
−
n
1-n
1−n中,有
a
1
a_1
a1,
a
2
a_2
a2···,
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n)这
ϕ
(
n
)
{\phi(n)}
ϕ(n)个数与n互质
那么,a*
a
1
a_1
a1 , a*
a
2
a_2
a2 ,···, a*
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n)也与n互质
( a
a
1
a_1
a1
m
o
d
mod
mod
n
n
n ) (a
a
2
a_2
a2
m
o
d
mod
mod
n
n
n)··· (a
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n)
m
o
d
mod
mod
n
n
n)
=( a
a
1
a_1
a1 * a
a
2
a_2
a2 ··· a
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n))
m
o
d
mod
mod
n
n
n
=
a
ϕ
(
n
)
a^{\phi(n)}
aϕ(n) (
a
1
a_1
a1
a
2
a_2
a2···
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n))
m
o
d
mod
mod
n
n
n
即
a
ϕ
(
n
)
a^{\phi(n)}
aϕ(n) (
a
1
a_1
a1
a
2
a_2
a2···
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n)) ≡
a
1
a_1
a1
a
2
a_2
a2···
a
ϕ
(
n
)
a_{\phi(n)}
aϕ(n) (
m
o
d
mod
mod
n
n
n )
所以,
a
ϕ
(
n
)
a^{\phi(n)}
aϕ(n) ≡ 1 (
m
o
d
mod
mod
n
n
n )
4.3 简单推论
费马小定理: 当n是质数时, a ϕ ( p ) a^{\phi(p)} aϕ(p) ≡ 1 (mod p) ,即 a p − 1 a^{p-1} ap−1 ≡ 1 ≡ 1 ≡1 ( m o d (mod (mod p ) p) p)
5. 快速幂
5.1 推导
α
k
\alpha^{k}
αk
=
α
2
x
1
\alpha^{2^{x_{1}}}
α2x1 *
α
2
x
2
\alpha^{2^{x_{2}}}
α2x2 ···
α
2
x
k
\alpha^{2^{x_{k}}}
α2xk
=
α
2
x
1
+
2
x
2
+
⋅
⋅
⋅
+
2
x
t
\alpha^{2^{x_{1}} + 2^{x_{2}} +···+ 2^{x_{t}}}
α2x1+2x2+⋅⋅⋅+2xt
即k=
2
x
1
2^{x_{1}}
2x1+
2
x
2
2^{x_{2}}
2x2+···+
2
x
t
2^{x_{t}}
2xt
α
1
\alpha^{1}
α1
α
2
1
\alpha^{2^{1}}
α21=
α
2
0
\alpha^{2^{0}}
α20 *
α
2
0
\alpha^{2^{0}}
α20
α
2
2
\alpha^{2^{2}}
α22=
α
2
1
\alpha^{2^{1}}
α21 *
α
2
1
\alpha^{2^{1}}
α21
···
α
2
l
o
g
2
k
\alpha^{2^{log_2k}}
α2log2k=
α
2
l
o
g
2
k
−
1
\alpha^{2^{log_2k-1}}
α2log2k−1 *
α
2
l
o
g
2
k
−
1
\alpha^{2^{log_2k-1}}
α2log2k−1
例:
4
5
4^5
45=
4
(
101
)
2
4^{(101)_2}
4(101)2=
4
0
4^0
40 *
4
2
4^2
42
a
=
4
,
k
=
5
,
p
=
10
,
r
e
s
=
1
a = 4 , k = 5 , p = 10 , res =1
a=4,k=5,p=10,res=1
r
e
s
=
r
e
s
∗
a
res = res * a
res=res∗a
m
o
d
mod
mod
p
;
p;
p;
k
>
>
=
1
;
k >> = 1 ;
k>>=1;
a
=
a
∗
a
a=a*a
a=a∗a
m
o
d
mod
mod
p
p
p;
5.2 代码
typedef long long ll;
//返回a^k mod p
int qmi(int a,int k,int p)
{
int res=1;
while(k)
{
if(k&1) res=(ll)res*a%p;
k>>=1;
a=(ll)a*a%p;
}
return res;
}
6. 逆元
6.1 乘法逆元
定义 若整数
b
,
m
b,m
b,m互质,并且
b
∣
a
b|a
b∣a,则存在一个整数
x
x
x,使得
a
/
b
a/b
a/b
≡
a
∗
x
≡ a*x
≡a∗x
(
m
o
d
(mod
(mod
m
)
m)
m),则称
x
x
x为
b
b
b的模
m
m
m乘法逆元,记为
b
−
1
b^{-1}
b−1 (
m
o
d
mod
mod
m
m
m)。
b
b
b 存在乘法逆元
<
=
=
>
<==>
<==>
b
b
b与
m
m
m互质
根据费马小定理,当
m
m
m为质数时,
b
m
−
2
b^{m-2}
bm−2即为
b
b
b的乘法逆元。
b
∗
x
b*x
b∗x
≡
1
≡ 1
≡1
(
m
o
d
(mod
(mod
m
)
m)
m)
b
m
−
1
b^{m-1}
bm−1
≡
1
≡ 1
≡1
(
m
o
d
(mod
(mod
m
)
m)
m)
b
∗
b
m
−
2
b*b^{m-2}
b∗bm−2
≡
1
≡ 1
≡1
(
m
o
d
(mod
(mod
m
)
m)
m)
−
−
>
-->
−−>
x
x
x
=
=
=
b
m
−
2
b^{m-2}
bm−2
7. 扩展欧几里得
7.1 裴蜀定理
定理 若
a
,
b
a,b
a,b是整数,且
g
c
d
(
a
,
b
)
=
d
gcd(a,b)=d
gcd(a,b)=d,那么对于任意的整数
x
,
y
x,y
x,y,
a
∗
x
+
b
∗
y
a*x+b*y
a∗x+b∗y 都一定是
d
d
d的倍数。特别地,一定存在整数
x
,
y
x,y
x,y,使
a
∗
x
+
b
∗
y
=
d
a*x+b*y=d
a∗x+b∗y=d 成立。
证明
因为
d
∣
a
,
d
∣
b
,
d|a,d|b,
d∣a,d∣b, 所以
d
∣
(
a
x
+
b
y
)
d|(ax+by)
d∣(ax+by)
7.2 扩展欧几里得
证明
a
∗
x
1
+
b
∗
y
1
=
g
c
d
(
a
,
b
)
a*x_1+b*y_1=gcd(a,b)
a∗x1+b∗y1=gcd(a,b)
b
∗
x
2
+
(
a
b*x_2+(a
b∗x2+(a
m
o
d
mod
mod
b
)
∗
y
2
b)*y_2
b)∗y2
=
g
c
d
(
b
,
a
= gcd(b,a
=gcd(b,a
m
o
d
mod
mod
b
)
b)
b)
因为
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)
=
=
=
g
c
d
(
b
,
gcd(b,
gcd(b,
a
a
a
m
o
d
mod
mod
b
)
b)
b)
其中,
a
a
a
m
o
d
mod
mod
b
b
b
=
a
−
=a-
=a−
⌊
a
/
b
⌋
\lfloor a/b \rfloor
⌊a/b⌋
∗
b
*b
∗b
那么,
b
∗
x
2
+
b*x_2+
b∗x2+(a
m
o
d
mod
mod
b
)
∗
y
2
b)*y_2
b)∗y2
=
b
∗
x
2
+
=b*x_2+
=b∗x2+(a-
⌊
a
b
⌋
\lfloor \frac{a}{b} \rfloor
⌊ba⌋
∗
b
)
∗
y
2
*b)*y_2
∗b)∗y2
=
a
∗
y
2
=a*y_2
=a∗y2
+
+
+
b
∗
(
x
2
b*(x_2
b∗(x2 -
⌊
a
b
⌋
\lfloor \frac{a}{b} \rfloor
⌊ba⌋*
y
2
y_2
y2
)
)
)
推得
x
1
=
y
2
x_1=y_2
x1=y2
y
1
=
y_1=
y1=
x
2
x_2
x2
−
-
−
⌊
a
b
⌋
\lfloor \frac{a}{b} \rfloor
⌊ba⌋*
y
2
y_2
y2
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
int a,b,x,y;
scanf("%d%d",&a,&b);
exgcd(a,b,x,y);
printf("%d %d\n",x,y);
return 0;
}
8. 线性同余方程
给定
a
,
b
,
m
a,b,m
a,b,m,求
x
x
x,使得
a
∗
x
≡
b
a*x≡b
a∗x≡b
(
m
o
d
(mod
(mod
m
)
m)
m)
解
∃
\exists
∃
y
y
y
∈
\in
∈
Z
Z
Z ,
s
t
.
st.
st.
a
∗
x
≡
a*x≡
a∗x≡
m
∗
y
+
b
m*y+b
m∗y+b
a
∗
x
−
m
∗
y
=
b
a*x-m*y=b
a∗x−m∗y=b
令
y
′
=
−
y
y'=- y
y′=−y
根据裴蜀定理可知
a
∗
x
+
m
∗
y
′
=
b
a*x+m*y'=b
a∗x+m∗y′=b 当且仅当
g
c
d
(
a
,
m
)
∣
b
gcd(a,m)|b
gcd(a,m)∣b时有解
解为
x
=
x
∗
x=x*
x=x∗
b
g
c
d
(
a
,
m
)
\frac{b}{gcd(a,m)}
gcd(a,m)b
m
o
d
mod
mod
m
m
m
9.中国剩余定理(孙子定理)
9.1 定理说明
{ x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) ⋅ ⋅ ⋅ x ≡ a n ( m o d m n ) \begin{cases} x ≡ a_1 (mod\ m_1)\\ x ≡ a_2 (mod\ m_2)\\ ···\\ x ≡ a_n (mod\ m_n)\\ \end{cases} ⎩ ⎨ ⎧x≡a1(mod m1)x≡a2(mod m2)⋅⋅⋅x≡an(mod mn)
假定整数
m
1
,
m
2
⋅
⋅
⋅
m
n
m_1,m_2···m_n
m1,m2⋅⋅⋅mn两两互质,则对任意的整数:
a
1
,
a
2
⋅
⋅
⋅
a
n
a_1,a_2···a_n
a1,a2⋅⋅⋅an,方程组
S
S
S有解。
方程的解为:
x
=
∑
i
=
1
n
a
i
∗
t
i
∗
M
i
x=\sum_{i=1}^{n} a_i*t_i*M_i
x=i=1∑nai∗ti∗Mi
其中,
M
=
∏
i
=
1
n
m
i
M=\prod_{i=1}^{n} m_i
M=∏i=1nmi
M
i
=
M
m
i
M_i=\frac{M}{m_i}
Mi=miM
t
i
=
m
i
−
1
(
m
o
d
M
i
)
t_i=m_i^{-1} (mod\ M_i)
ti=mi−1(mod Mi)