数论合集

注:本文讨论都在正整数范围内。

质数

定义

我们把只能被 1 和它本身整除的数称为质数。

质数的判定

试除法

n 以内的数一个个试除,来判定是否是质数。

时间复杂度:O(n)

埃氏筛

2 开始,如果当前数没有被筛去,那么用这个数筛掉 2×n3×n 的数,没有被筛去的即为质数。

时间复杂度:O(nlogn)

埃氏筛的优化

不难发现我们可以直接从 n×n 开始筛。

因为对于一个 i×n(2i<n),它一定被 i 的最小质因子筛掉过,所以这样可以避免大部分的重复筛。

for(int i=2;i<=n;i++){
	if(!st[i]){
		prime[++cnt]=i;
	}
	for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
		st[i*prime[j]]=1;
	}
}

时间复杂度:O(nloglogn)

线性筛

我们要求每个合数只被它的最小质因子筛掉。

我们令 fxx 的最小质因子,那么一个合数 n 仅会在 i=nfn 时筛去。

for(int i=2;i<=n;i++){
	if(!st[i]){
		prime[++cnt]=i;
	}
	for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
		st[i*prime[j]]=1;
		if(i%prime[j]==0) break;
	}
}

欧拉函数

定义

欧拉函数 φ(n) 代表 1n 中与 n 互质的数的个数。

性质

  1. 对于一个质数,φ(n)=n1

  2. 对于两个互质的数 a,b,满足 φ(a)φ(b)=φ(ab)。满足这个条件的函数称为积性函数,例如 f(x)=114514x 也是积性函数。

  3. d|nφ(n)=n

  4. p 为质数,则 φ(pa)=papa1

计算

法1 试除法

考虑一个数 pk 的欧拉函数。若一个数与 pk 不互质,那么这个数一定是 p 的倍数。每 p 个数中就会有一个 p 的倍数,那么 1pk 中就有 pkp 个数与 pk 不互质。那么 φ(pk)=pkpkp=pk(11p)。所以我们将一个数 n 分解质因数 p1k1×p2k2×p3k3××pmkm。根据欧拉函数积性函数的性质,φ(n)=n(11p1)(11p2)(11p3)(11pm)。这个方法是 O(n) 的。

法2 线性筛

我们可以利用欧拉函数积性函数的性质,若我们知道 φ(a)φ(b),就可以推出 φ(ab)。做这件事的之前,我们要把 1n 的质数筛出来用于递推。

在线性筛时,我们干:

  1. i 为质数,则 φ(i)=i1

  2. i=pkp 为质数),则有 φ(i)=pkiφ(p)

  3. i=p1p2,则 φ(i)=φ(p1p2)

void getphi(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!st[i]){
			prime[cnt++]=i;
			phi[i]=i-1;
		}
		for(int j=0;prime[j]<=n/i;j++){
			int t=prime[j]*i;
			st[t]=1;
			if(i%prime[j]==0){
				phi[t]=phi[i]*prime[j];
				break;
			}
			phi[t]=phi[i]*(prime[j]-1);
		}
	}
} 

模运算

定义

我们令 amodba÷b 的余数。

amodm=bmodm,则我们记为 ab(modm)

性质

  1. 0amodbb1

  2. (a+b)modm=(amodm+bmodm)modm

  3. (ab)modm=(amodmbmodm+m)modm

  4. (a×b)modm=(amodm×bmodm)modm

  5. abmodm=(amodm)bmodm

  6. ab(modm)ba(modm)

  7. ab(modm),bc(modm)ac(modm)

  8. ab(modm)(a±c)(b±c)(modm)

  9. ab(modm)(a×c)(b×c)(modm)

应用

求 gcd(辗转相除法)

辗转相除法依赖于定理:gcd(a,b)=gcd(b,amodb)

证明

m=amodb,则 a 可以表示为 kb+m,进一步有 m=akb

ga,b 的一个公因数,那么 g|a,g|b

m=akb,g|a,g|b

g|m

g 也是 b,amodb 的公因数。

int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}

裴蜀定理

g=gcd(a,b),则 ax+by=k 有解当且仅当 g|k

扩展欧几里得算法

判定 ax+by=gcd(a,b) 有解后,我们需要来解这个方程。

先推一波式子:

ax+by=gcd(a,b)

ax+by=gcd(b,amodb)

bx+(amodb)y=gcd(b,amodb)

bx+(aab)y=gcd(b,amodb)

ay+b(xaby)=gcd(b,amodb)

容易发现此时 x 变成了 yy 变成了 xaby

于是我们就可以递归求解了。

void Exgcd(int a,int b,int &x,int &y) {
	if(!b){
		x=1,y=0;
	}
	else{
		Exgcd(b,a%b,y,x);
		y-=a/b*x;
	}
}

乘法逆元

定义

ax1(modm),则称 xamodm 意义下的数论倒数(即乘法逆元),记为 a1(modm)inv(a).

性质

  1. modm 意义下,÷a 等价于 ×a1(modm)

  2. amodm 意义下有逆元,当且仅当 gcd(a,m)=1
    证明:
    那么我们求逆元相当于解 ax1(modm)
    ax1(modm) 等价于 ax=1my
    变形得 ax+my=1
    根据裴蜀定理可得只有 gcd(a,m)=1 时,原方程有解,即 amodm 意义下有逆元。

求逆元

费马小定理求逆元

费马小定理:若 b 为质数,且 a,b 互质,则 ab11(modb)

给式子变形,得 a×ab21(modb)

于是我们可以得出 ab2amodb 意义下互为乘法逆元。

exgcd 求逆元

我们将 ax1(modm) 转化为 ax+by=1,用 exgcd 求解即可。

中国剩余定理

给出一个一元线性同余方程组:

{xa1(modm1)xa2(modm2)xan(modmn)

中国剩余定理可以判定该方程组是否有解以及解的具体形式。

具体咋做还没学。

posted @   luqyou  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示