质数与约数
质数与约数
素数判断及筛法
试除法
若有一个正整数 \(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)
\]

浙公网安备 33010602011771号