常见数论-定理

~ 2025-7-12 11:19:35

1、费马小定理

  • 若存在整数 a,pa , p 且gcd(a,p)=1,即二者互质,则有ap11a^{p-1} ≡ 1 (modp)(\, mod \: p)
  • (这里的 ≡ 指的是恒等于,ap11a^{p-1} ≡ 1 (modp)(\, mod \: p) 是指aa(p1)(p-1)次幂取模pp11取模pp恒等)

费马小定理的两种等价形式

  • 基本形式:若p为素数,a为任意整数则apaa^p ≡ a (modp)(\, mod \: p)
  • 常用形式:若aapp互质,则ap11a^{p-1} ≡ 1 (modp)(\, mod \: p)

2、容斥原理

3、乘法逆元

同时: 若整数 bmb,m 互质,并且对于任意的整数 aa,如果满足 bab|a(bb能整除aa),则存在一个整数 xx,使得 aba×x(mod\frac{a}{b}≡a × x(mod   m),则称x x b b 的模 mm 乘法逆元,记为 b1b^{−1}(mod  m)。

bb 存在乘法逆元的充要条件是 bb 与模数 mm 互质。当模数 mm 为质数时,bm2b^{m−2} 即为 bb 的乘法逆元。

4、整数唯一分解定理

整数唯一分解定理:亦称算术基本定理,是数论的重要定理之一。

该定理断言:任何一个大于1的整数n都可以分解成若干个素因数的连乘积,如果不计各个素因数的顺序,那么这种分解是惟一的,即若n>1,则有:

  • (1) n=p1p2pmn = p_1*p_2*…*p_m;

其中p1p2pmp_1≤p_2≤…≤p_m皆素数,上式常简记为:

  • (2) n=p1a1p2a2...pkakn = p_1^{a_1} * p_2^{a_2} * ...* p_k^{a_k}

其中,p1<p2<<pkp_1<p_2<…<p_k皆素数,ai(i=12k)a_i(i=1,2,…,k)皆正整数. (2) 式称为n的标准分解式,又称为质因数分解式、素数幂分解式等,若(2)式成立,则n的任一正因数d都可表示成:

  • (3) d=p1b1p2b2...pkbkd = p_1^{b_1} * p_2^{b_2} * ...* p_k^{b_k}

其中aibi0(i=12k)a_i≥b_i≥0 (i=1,2,…,k).

标准分解式的应用: 利用标准分解式(可查素数幂分解表)容易写出任二正整数的最大公因数。

即若有n=p1a1p2a2...pkakn = p_1^{a_1} * p_2^{a_2} * ...* p_k^{a_k}m=p1b1p2b2...pkbkm = p_1^{b_1} * p_2^{b_2} * ...* p_k^{b_k}. 其中ai0,bi0a_i≥0,b_i≥0。则m,nm,n的最大公约数gcd(m,n)=p1r1p2r2...pkrkgcd(m,n) = p_1^{r_1} * p_2^{r_2} * ...* p_k^{r_k}. 其中ri=min(ai,bi)(i=12k)r_i = min(a_i,b_i)(i=1,2,…,k)

5.埃氏筛

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int n;
bool sieve[N]; // true被筛选过,false未被筛选过 
int main(){
	scanf("%d", &n);
	sieve[0] = true; // 被筛选过 
	sieve[1] = true; // 被筛选过 
	for(int i = 2; i * i <= n; i++){
		if(!sieve[i]){ // i没有被筛选过,则说明i是素数 
			for(int j = i*i; j <= n; j += i){
				sieve[j] = true;
			} 
		}
	}
	for(int i = 0; i <= n; i++){
		if(!sieve[i]) printf("%d ", i);
	} 
	return 0;
}

6.欧拉筛(线性筛)

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int n, ans = 0;
bool sieve[N];
int prime[N];
int main(){
	scanf("%d", &n);
	sieve[0] = true; // 筛选过
	sieve[1] = true; // 筛选
	for(int i = 2; i <= n; i++){
		if(!sieve[i]) prime[ans++] = i;// i是素数,加入数组prime
		for(int j = 0; j < ans; j++){
			if(prime[j] * i > n) break; // 如果超出n,就没必要筛选了 
			sieve[prime[j] * i] = true;
			// 如果i是prime[j]的倍数,则i一定可以表示成prime[j]*k的模式
			// 也就是,i*prime[j]早就被i的质因子prime[j]筛选过了 
			if(i % prime[j] == 0) break;
		} 
	} 
	for(int i = 0; i < ans; i++){
		printf("%d ", prime[i]);
	} 
	return 0;
}



我们会审查剪贴板内容,并对发布不合适内容的同学进行相应的处理