Loading

质数与约数

质数与约数

素数判断及筛法

试除法

若有一个正整数 \(n\) 为合数,则存在一个能整除 \(n\) 的数 \(d\),且 \(2\le d \le \sqrt{n}\) 。因此我们只需要扫描 2 ∼ \(n\) 之间的所有整数,依次检查它们能否整除 n,若都不能整除,则 n 为质数,否则 n 为合数。注意,我们还需要特判 0 和 1 这两个整数。

时间复杂度 \(O(\sqrt n)\)

bool is_prime(int n){
	if(n<2)return false;
	for(int i=1,sq=sqrt(n);i<=sq;i++){
		if(n%i==0)return false;
	}
	return true;
}

埃氏筛

对于每个质数 \(p\) 而言,小于 \(p^2\)\(p\) 的倍数在扫描到更小的质数时就已经被标记过了。

于是从 \(p^2\) 开始扫。

void found_prime() {
	memset(vis, 0, sizeof(vis));
	vis[0] = 1; vis[1] = 1; // 特殊处理 0 和 1
	for(int i=2; i<=n; ++i) {
		if(!vis[i]) { // i 为质数
		for(int j=i*i; j<=n; j+=i)
			vis[j] = 1; // 标记合数
		}
	}
}

线性筛

#include<bits/stdc++.h>
using namespace std;
const int N=1e8+50;
int prime[N],cnt;
bool vis[N];
int n,q;
void init(){
	for(int i=2;i<=n;i++){
		if(!vis[i])prime[++cnt]=i;
		for(int j=1;j<=cnt&&prime[j]<=n/i;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
}
int main(){
	scanf("%d%d",&n,&q);
	init();
	while(q--){
		int x;
		scanf("%d",&x);
		printf("%d\n",prime[x]);
	}
}

素性测试

算数基本定理

算术基本定理又名唯一分解定理,任何一个大于 1 的正整数都能唯一分解为若干个质数的乘积。

(这东西太简单就不证了吧)

推论1: \(n\) 的正约数个数为:

\[(c_1+1)\times(c_2+1)\times\cdots\times(c_m+1)=\prod_{i=1}^{m}(c_i+1) \]

推论2: \(n\) 的所有正约数的和为:

\[(1+p_1+p_1^2+\cdots +p_1^{c_1})\times\cdots\times(1+p_m+p_m^2+\cdots +p_m^{c_m})=\prod_{i=1}^m(\sum_{j=0}^{c_i}(p_i)^j) \]

posted @ 2023-02-27 08:52  流泪的小酒窝  阅读(86)  评论(0)    收藏  举报