数论

数论基础#

整除#

只在整数域上讨论。

一般形式为 a|b ,叫做 a 能整除 b

其性质在此不过多叙述。

约数#

与整除相关。若 a|b ,则称 ba 的倍数,ab 的约数。

在具体问题中,如果没有特别说明,约数总是指正约数

最大公因数和最小公倍数#

(a,b)[a,b] ,有 (a)[a]=a 的性质。

最大公约数有如下性质:

  • (a1,,an)=(|a1|,,|an|)
  • (a,b)=(b,a)
  • a0,则 (a,0)=(a,a)=|a|
  • (bq+r,b)=(r,b)]
  • (a1,,an)=((a1,a2),a3,,an)。进而 1<k<n1, (a1,,an)=((a1,,ak),(ak+1,,an))
  • 对不全为 0 的整数 a1,,an 和非零整数 m(ma1,,man)=|m|(a1,,an)
  • 对不全为 0 的整数 a1,,an,若 (a1,,an)=d,则 (a1/d,,an/d)=1
  • (an,bn)=(a,b)n

最小公倍数有如下性质:

  • [a1,,an]=[|a1|,,|an|]
  • [a,b]=[b,a]
  • a0,则 [a,1]=[a,a]=|a|
  • ab,则 [a,b]=|b|
  • [a1,,an]=[[a1,a2],a3,,an]。进而 1<k<n1, [a1,,an]=[[a1,,ak],[ak+1,,an]]
  • aim, 1in,则 [a1,,an]m
  • [ma1,,man]=|m|[a1,,an]
  • [a,b,c][ab,ba,ca]=[a,b][b,c][c,a]
  • [an,bn]=[a,b]n

最大公约数和最小公倍数可以组合出很多奇妙的等式,如:

  • (a,b)[a,b]=|ab|
  • (ab,bc,ca)[a,b,c]=|abc|
  • (a,b,c)2(a,b)(b,c)(a,c)=[a,b,c]2[a,b][b,c][a,c]

ex:一些作者认为 00 的最大公约数无定义,其余作者一般将其视为 0。C++ STL 的实现中采用后者,即认为 00 的最大公约数为 0

互素#

(a1,a2)=1,则称 a1a2 互素既约)。

多个整数互素,不一定两两互素。例如 61015 互素,但是任意两个都不互素。

素数#

若一整数 p0,±1 满足 p 除了 1 和它本身的约数外没有其他约数,则称这个数为约数,反之即为和数。

算术基本引理#

通过素数的性质我们可得:

p 为素数,且 p|a1a2,那么 p|a1p|a2 成立。

算术基本定理(唯一分解定理)#

设一正整数 a,必有:

a=p1k1p2k2...pnkn,p1<p2<...<pn

这样的形式称作 a 的标准素因数分解式。

同余#

即除以某数的余数相同。

记为同余式:ab(modp)

ex若没有特殊说明,模数总是正整数。

性质:

  • 同余是等价关系,即同余具有
    • 自反性:aa(modm)
    • 对称性:若 ab(modm),则 ba(modm)
    • 传递性:若 ab(modm),bc(modm),则 ac(modm)
  • 线性运算:若a,b,c,dZ,mN,ab(modm),cd(modm),则有:
    • a±cb±d(modm)
    • a×cb×d(modm)

积性函数#

定义:若 F(xy)=F(x)F(y),gcd(a,b)=1,则称函数 F(x) 为积性函数。

欧拉函数 φ(x) 就是典型的积性函数。

ex:若当 gcd(a,b)1 时仍有 F(xy)=F(x)F(y),则称F(x) 为完全积性函数。

筛法#

埃拉托斯特尼筛法(埃氏筛)#

过程

考虑这样一件事情:对于任意一个大于 1 的正整数 n,那么它的 x 倍就是合数(x1 )。利用这个结论,我们可以避免很多次不必要的检测。

如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。

vector<intprime;
bool is_prime[N];
void Eratosthenes(int n) {
    is_prime[0]=is_prime[1]=0;
    for(int i=2;i<=n;++i) is_prime[i]=true;
    for(int i=2;i<=n;++i){
        if (is_prime[i]){
            prime.push_back(i);
            if((long long)i*i>n) continue;
            for(int j=i*i;j<=n;j+=i) is_prime[j]=false;
        }
    }
}

时间复杂度为 O(nloglogn),已经很接近线性了。其实还可以只对前一半进行筛法,结合只筛奇数以及位运算的知识,可以把复杂度降为 O(n),若是再加上分块,可变为 O(n+S)S 为一常数。

线性筛(欧拉筛)#

我们每次对于一个数,只选择其最小质因子进行标记,当 imodpri[j]=0 时意味着这已经有更小的数标记过当前数,所以退出循环。

int pri[1000010];
bool isp[N],cnt=0;
void prime(int n){
    memset(isp,1,sizeof(isp));
    isp[1]=0;
    for(int i=2;i<=n;++i){
        if(isp[i]) pri[++cnt]=i;
        for(int j=1;j<=cnt && i*pri[j]<=n;++j){
            isp[i*pri[j]]=0;
            if(i%pri[j]==0) break;
        }
    }
}

这样优化,时间复杂度降为 O(n)

拓展

筛法可以处理欧拉函数 φ(n),只需再添几行代码:

int pri[1000010];
bool isp[N],cnt=0;
int phi[1000010];
void prime(int n){
    memset(isp,1,sizeof(isp));
    isp[1]=0;
    phi[1]=1;
    for(int i=2;i<=n;++i){
        if(isp[i]) pri[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt && i*pri[j]<=n;++j){
            isp[i*pri[j]]=0;
            if(i%pri[j]==0){
				phi[i*pri[j]]=phi[i]*pri[j];
                break;
            }
            phi[i*pri[j]]=phi[i]*phi[pri[j]];
        }
    }
}

逆元#

定义 ax1(modb),则称 xa 在模 b 意义下的逆元。记作 a1

求法

  1. 拓展欧几里得法
void exgcd(int a, int b, int& x, int& y) {
  	if (b == 0) {
    	x = 1, y = 0;
    	return;
  	}
  	exgcd(b, a % b, y, x);
  	y -= a / b * x;
}

本质上是一个原理。

  1. 快速幂法

因为有 ap11(modp),所以有 ap2a1(modp),所以 ap2 即为逆元。

int qpow(long long a, int b) {
  	int ans = 1;
  	a = (a % p + p) % p;
  	for (; b; b >>= 1) {
    	if (b & 1) ans = (a * ans) % p;
    	a = (a * a) % p;
  	}
  	return ans;
}
  1. 线性求法(不会证,自己搜)
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
  inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}

中国剩余定理(CRT)#

可求解如下形式的一元线性同余方程组(其中 n1,n2,,nk 两两互质):

{xa1(modn1) xa2(modn2)  xak(modnk) 

上面的「物不知数」问题就是一元线性同余方程组的一个实例。

过程#

  1. 计算所有模数的积 n
  2. 对于第 i 个方程:
    1. 计算 mi=nni
    2. 计算 mi 在模 [ni 意义下的 逆元 mi1
    3. 计算 ci=mimi1不要对 ni 取模)。
  3. 方程组在模 n 意义下的唯一解为:x=i=1kaici(modn)
LL CRT(int k, LL* a, LL* r) {
  	LL n = 1, ans = 0;
  	for (int i = 1; i <= k; i++) n = n * r[i];
  	for (int i = 1; i <= k; i++) {
    	LL m = n / r[i], b, y;
    	exgcd(m, r[i], b, y);  // b * m mod r[i] = 1
    	ans = (ans + a[i] * m * b % n) % n;
  	}
  	return (ans % n + n) % n;
}

作者:God_Max_Me

出处:https://www.cnblogs.com/lizihan00787/p/18685868

版权:本作品采用「God_Max_Me-非商业性使用」许可协议进行许可。

posted @   God_Max_Me  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示