数论基础知识
1. 质数
质数:在大于1的整数中,只包含1和它本身这两个约数的数。
nnn中最多只包含一个大于sqrt(n)sqrt(n)sqrt(n)的质因子。
1.1 质数的判定
试除法 O(sqrt(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(log(n))O( log(n) )O(log(n))~O(sqrt(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 约数个数
对NNN质因数分解
NNN=p1α1p_1^{α_1}p1α1p2α2p_2^{α_2}p2α2p3α3p_3^{α_3}p3α3…pnαnp_n^{α_n}pnαn
其中ppp为质数,1~NNN对pip_ipi的倍数有pi0p_i^{0}pi0,pi1p_i^{1}pi1…piαip_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 约数之和
约数之和= (p10p_1^{0}p10+p11p_1^{1}p11+p12p_1^{2}p12…p1α1p_1^{α_1}p1α1)(p20p_2^{0}p20+p21p_2^{1}p21+p22p_2^{2}p22…p2α1p_2^{α_1}p2α1) …(pn0p_n^{0}pn0+pn1p_n^{1}pn1+pn2p_n^{2}pn2…pnαnp_n^{α_n}pnαn)
ttt=1
ttt=p1p_1p1+1
…
ttt=p1p_1p1*( p1α1−2p_1^{α_1-2}p1α1−2+…+ p10p_1^{0}p10 )+1
ttt=p1p_1p1* ( p1p_1p1*( p1α1−2p_1^{α_1-2}p1α1−2+…+ p10p_1^{0}p10 )+1 ) +1
ttt=p1α1p_1^{α_1}p1α1+…+ p12p_1^{2}p12+p11p_1^{1}p11+p10p_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 最大公约数(欧几里得算法)
ddd可以整数aaa,ddd可以整数bbb,那么ddd可以整数a∗x+b∗ya*x+b*ya∗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~NNN中与NNN互质的数的个数被称为欧拉函数
N= p1α1p_1^{α_1}p1α1 p2α2p_2^{α_2}p2α2 ··· pkαkp_k^{α_k}pkαk
Φ(N)\Phi (N)Φ(N)=N(1-1p1\frac{1}{p_1}p11)(1-1p2\frac{1}{p_2}p21)···(1-1pk\frac{1}{p_k}pk1)
3.2 证明
3.2.1 证明
根据容斥原理
Φ(N)\Phi(N)Φ(N)=NNN
-Np1\frac{N}{p_1}p1N -Np2\frac{N}{p_2}p2N -···- Npk\frac{N}{p_k}pkN
+Np1∗p2\frac{N}{p_1*p_2}p1∗p2N+Np1∗p3\frac{N}{p_1*p_3}p1∗p3N +···+Npk−1∗pk\frac{N}{p_{k-1}*p_{k}}pk−1∗pkN
-Np1∗p2∗p3\frac{N}{p_1*p_2*p_3}p1∗p2∗p3N -Np1∗p2∗p4\frac{N}{p_1*p_2*p_4}p1∗p2∗p4N -···-Npk−2∗pk−1∗pk\frac{N}{p_{k-2}*p_{k-1}*p_{k}}pk−2∗pk−1∗pkN
+Np1∗p2∗p3∗p4\frac{N}{p_1*p_2*p_3*p_4}p1∗p2∗p3∗p4N+Np1∗p2∗p3∗p5\frac{N}{p_1*p_2*p_3*p_5}p1∗p2∗p3∗p5N+··· Npk−3∗pk−2∗pk−1∗pk\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)iii为质数,ϕ(i)\phi ( i )ϕ(i)= iii - 1
(2)iii modmodmod pjp_jpj ==0==0==0 时,ϕ(pj∗i)\phi( p_j * i )ϕ(pj∗i) = pjp_jpj * ϕ(i)\phi( i )ϕ(i)
(3)iii modmodmod pjp_jpj !=0!= 0!=0 时,ϕ(pj∗i)\phi(p_j * i)ϕ(pj∗i)= ϕ(pj)\phi (p_j)ϕ(pj) * ϕ(i)\phi( i )ϕ(i) = ϕ(i)\phi ( i )ϕ(i) * (pjp_jpj-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,ma,ma,m ∈∈∈ N+N^{+}N+,且 gcd(a,m)==1gcd (a,m) == 1gcd(a,m)==1,我们有
aϕ(m)a^{\phi(m)}aϕ(m) ≡1≡1≡1 (mod(mod(mod mmm)
4.2 证明
a,na ,na,n互质
1−n1-n1−n中,有a1a_1a1,a2a_2a2···,aϕ(n)a_{\phi(n)}aϕ(n)这ϕ(n){\phi(n)}ϕ(n)个数与n互质
那么,a*a1a_1a1 , a*a2a_2a2 ,···, a*aϕ(n)a_{\phi(n)}aϕ(n)也与n互质
( aa1a_1a1 modmodmod nnn ) (aa2a_2a2 modmodmod nnn)··· (aaϕ(n)a_{\phi(n)}aϕ(n) modmodmod nnn)
=( aa1a_1a1 * aa2a_2a2 ··· aaϕ(n)a_{\phi(n)}aϕ(n)) modmodmod nnn
=aϕ(n)a^{\phi(n)}aϕ(n) (a1a_1a1a2a_2a2···aϕ(n)a_{\phi(n)}aϕ(n)) modmodmod nnn
即 aϕ(n)a^{\phi(n)}aϕ(n) (a1a_1a1a2a_2a2···aϕ(n)a_{\phi(n)}aϕ(n)) ≡ a1a_1a1a2a_2a2···aϕ(n)a_{\phi(n)}aϕ(n) (modmodmod nnn )
所以,aϕ(n)a^{\phi(n)}aϕ(n) ≡ 1 (modmodmod nnn )
4.3 简单推论
费马小定理: 当n是质数时,aϕ(p)a^{\phi(p)}aϕ(p) ≡ 1 (mod p) ,即ap−1a^{p-1}ap−1 ≡1≡ 1≡1 (mod(mod(mod p)p)p)
5. 快速幂
5.1 推导
αk\alpha^{k}αk
=α2x1\alpha^{2^{x_{1}}}α2x1 * α2x2\alpha^{2^{x_{2}}}α2x2 ··· α2xk\alpha^{2^{x_{k}}}α2xk
=α2x1+2x2+⋅⋅⋅+2xt\alpha^{2^{x_{1}} + 2^{x_{2}} +···+ 2^{x_{t}}}α2x1+2x2+⋅⋅⋅+2xt
即k=2x12^{x_{1}}2x1+2x22^{x_{2}}2x2+···+2xt2^{x_{t}}2xt
α1\alpha^{1}α1
α21\alpha^{2^{1}}α21=α20\alpha^{2^{0}}α20 * α20\alpha^{2^{0}}α20
α22\alpha^{2^{2}}α22=α21\alpha^{2^{1}}α21 * α21\alpha^{2^{1}}α21
···
α2log2k\alpha^{2^{log_2k}}α2log2k=α2log2k−1\alpha^{2^{log_2k-1}}α2log2k−1 * α2log2k−1\alpha^{2^{log_2k-1}}α2log2k−1
例:454^545=4(101)24^{(101)_2}4(101)2=404^040 * 424^242
a=4,k=5,p=10,res=1a = 4 , k = 5 , p = 10 , res =1a=4,k=5,p=10,res=1
res=res∗ares = res * ares=res∗a modmodmod p;p;p;
k>>=1;k >> = 1 ;k>>=1;
a=a∗aa=a*aa=a∗a modmodmod ppp;
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,mb,mb,m互质,并且b∣ab|ab∣a,则存在一个整数xxx,使得a/ba/ba/b ≡a∗x≡ a*x≡a∗x (mod(mod(mod m)m)m),则称xxx为bbb的模mmm乘法逆元,记为b−1b^{-1}b−1 (modmodmod mmm)。
bbb 存在乘法逆元 <==><==><==> bbb与mmm互质
根据费马小定理,当mmm为质数时,bm−2b^{m-2}bm−2即为bbb的乘法逆元。
b∗xb*xb∗x ≡1≡ 1≡1 (mod(mod(mod m)m)m)
bm−1b^{m-1}bm−1 ≡1≡ 1≡1 (mod(mod(mod m)m)m)
b∗bm−2b*b^{m-2}b∗bm−2 ≡1≡ 1≡1 (mod(mod(mod m)m)m)
−−>-->−−> xxx === bm−2b^{m-2}bm−2
7. 扩展欧几里得
7.1 裴蜀定理
定理 若a,ba,ba,b是整数,且 gcd(a,b)=dgcd(a,b)=dgcd(a,b)=d,那么对于任意的整数x,yx,yx,y,a∗x+b∗ya*x+b*ya∗x+b∗y 都一定是ddd的倍数。特别地,一定存在整数x,yx,yx,y,使a∗x+b∗y=da*x+b*y=da∗x+b∗y=d 成立。
证明
因为d∣a,d∣b,d|a,d|b,d∣a,d∣b, 所以d∣(ax+by)d|(ax+by)d∣(ax+by)
7.2 扩展欧几里得
证明
a∗x1+b∗y1=gcd(a,b)a*x_1+b*y_1=gcd(a,b)a∗x1+b∗y1=gcd(a,b)
b∗x2+(ab*x_2+(ab∗x2+(a modmodmod b)∗y2b)*y_2b)∗y2 =gcd(b,a= gcd(b,a=gcd(b,a modmodmod b)b)b)
因为 gcd(a,b)gcd(a,b)gcd(a,b) === gcd(b,gcd(b,gcd(b, aaa modmodmod b)b)b)
其中,aaa modmodmod bbb =a−=a-=a− ⌊a/b⌋\lfloor a/b \rfloor⌊a/b⌋∗b*b∗b
那么,b∗x2+b*x_2+b∗x2+(a modmodmod b)∗y2b)*y_2b)∗y2
=b∗x2+=b*x_2+=b∗x2+(a-⌊ab⌋\lfloor \frac{a}{b} \rfloor⌊ba⌋∗b)∗y2*b)*y_2∗b)∗y2
=a∗y2=a*y_2=a∗y2+++b∗(x2b*(x_2b∗(x2 -⌊ab⌋\lfloor \frac{a}{b} \rfloor⌊ba⌋*y2y_2y2)))
推得
x1=y2x_1=y_2x1=y2
y1=y_1=y1= x2x_2x2 −-− ⌊ab⌋\lfloor \frac{a}{b} \rfloor⌊ba⌋*y2y_2y2
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,ma,b,ma,b,m,求xxx,使得a∗x≡ba*x≡ba∗x≡b (mod(mod(mod m)m)m)
解
∃\exists∃ yyy ∈\in∈ ZZZ ,st.st.st. a∗x≡a*x≡a∗x≡ m∗y+bm*y+bm∗y+b
a∗x−m∗y=ba*x-m*y=ba∗x−m∗y=b
令y′=−yy'=- yy′=−y
根据裴蜀定理可知
a∗x+m∗y′=ba*x+m*y'=ba∗x+m∗y′=b 当且仅当gcd(a,m)∣bgcd(a,m)|bgcd(a,m)∣b时有解
解为 x=x∗x=x*x=x∗ bgcd(a,m)\frac{b}{gcd(a,m)}gcd(a,m)b modmodmod mmm
9.中国剩余定理(孙子定理)
9.1 定理说明
{x≡a1(mod m1)x≡a2(mod m2)⋅⋅⋅x≡an(mod mn) \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)
假定整数m1,m2⋅⋅⋅mnm_1,m_2···m_nm1,m2⋅⋅⋅mn两两互质,则对任意的整数:a1,a2⋅⋅⋅ana_1,a_2···a_na1,a2⋅⋅⋅an,方程组SSS有解。
方程的解为:
x=∑i=1nai∗ti∗Mix=\sum_{i=1}^{n} a_i*t_i*M_ix=i=1∑nai∗ti∗Mi
其中,
M=∏i=1nmiM=\prod_{i=1}^{n} m_iM=∏i=1nmi
Mi=MmiM_i=\frac{M}{m_i}Mi=miM
ti=mi−1(mod Mi)t_i=m_i^{-1} (mod\ M_i)ti=mi−1(mod Mi)