1、素数筛选法(时间复杂度O(nloglogN)
/*
素数判断:素数筛选法(用素数筛选合数)
*/
#include <stdio.h>
#include <math.h>
#define MAX_N 100
//素数筛选法
int prime[MAX_N + 5] = {0};//初始化为0
void init() { //素数筛选法
for(int i=2;i<=MAX_N;i++) {
if(!prime[i]) {//素数时
prime[++prime[0]] = i;//prime[0]记录素数的个数,后面的依次储存素数
for(int j=i*i;j<=MAX_N;j+=i) { //此素数的倍数必为合数(可以不必从2*i开始筛)
prime[j] = 1;//筛去
}
}
}
}
int main() {
init();
printf("prime[0]:%d\n",prime[0]);
for(int i=1;i<=prime[0];i++) {
printf("%d ",prime[i]);
}
printf("\n");
return 0;
}
2、应用:求1~n中每个数的最小素因子
/*
求2~n内每个数的最小素因子
*/
#include <stdio.h>
#include <math.h>
#define MAX_N 100
int prime[MAX_N + 5] = {0};//初始化为0
void init() {
for(int i=2;i<=MAX_N;i++) {
if(!prime[i]) {
prime[i] = i; //素数的最小素因子为她本身
for(int j=2*i;j<=MAX_N;j+=i) {//可以令j从i开始循环,这样可以省略上面那句话
if(!prime[j])
prime[j] = i;
}
}
}
}
int main() {
init();
for(int i=2;i<MAX_N;i++) {
printf("MIN_factory[%d] = %d\n",i,prime[i]);
}
return 0;
}
3、线性筛选(欧拉筛选,时间复杂度O(n))
/*
素数判断:线性筛选
*/
#include <stdio.h>
#include <math.h>
#define MAX_N 100
//线性筛选(欧拉筛选)
int prime[MAX_N + 5] = {0};//初始化为0
void init() {
for(int i=2;i<=MAX_N;i++) {
if(!prime[i]) {
prime[++prime[0]] = i; //prime[0]记录素数的个数,后面依次储存素数(从prime[1]开始
}
for(int j=1;j<=prime[0];j++) {
if(i*prime[j] > MAX_N) break;//只需标记MAX_N以内的素数
prime[i*prime[j]] = 1;
if(i%prime[j] == 0) break;//关键步骤,避免重复筛选
}
}
}
int main() {
init();
for(int i=1;i<=prime[0];i++) {
printf("%d ",prime[i]);
}
printf("\n");
return 0;
}
4、应用,求第10001个素数
/*
求第10001个素数
*/
#include <stdio.h>
#include <math.h>
#define MAX_N 200000
//线性筛选(欧拉筛选)
int prime[MAX_N + 5] = {0};//初始化为0
void init() {
for(int i=2;i<=MAX_N;i++) {
if(!prime[i]) {
prime[++prime[0]] = i; //prime[0]记录素数的个数,后面依次储存素数(从prime[1]开始
}
for(int j=1;j<=prime[0];j++) {
if(i*prime[j] > MAX_N) break;//只需标记MAX_N以内的素数
prime[i*prime[j]] = 1;
if(i%prime[j] == 0) break;//关键步骤,避免重复筛选
}
}
}
int main() {
init();
printf("%d\n",prime[10001]);
return 0;
}
答案是:104743
5、应用,求2~N内每个数的质因数个数
/*
求2~N内每个素的质因数个数,如2的质因数个数为2(1,2),4的质因数个数为3(1,2,4)
*/
#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX_N 100
int prime[MAX_N+5] = {0};
int factory_cnt[MAX_N] = {0};
void init() {
//前半部分是线性筛选,后半部分是质因数分解定理
for(int i=2;i<=MAX_N;i++) {
if(!prime[i])
prime[++prime[0]] = i;
for(int j=1;j<prime[0];j++) {
if(i*prime[j] > MAX_N) break;
prime[i*prime[j]] = 1;
if(i%prime[j]==0) break;
}
int tem = i;
int j = 1;
int cnt ,ans = 1;
while(tem!=1) {
cnt = 0;
while(tem%prime[j]==0) {
cnt++;
tem /= prime[j];
}
ans *= (1+cnt);
j++;
}
factory_cnt[i] = ans;
}
}
int main() {
init();
for(int i=2;i<=MAX_N;i++) {
printf("%d ",factory_cnt[i]);
}
printf("\n");
}
输出
2 2 3 2 4 2 4 3 4 2 6 2 4 4 5 2 6 2 6 4 4 2 8 3 4 4 6 2 8 2 6 4 4 4 9 2 4 4 8 2 8 2 6 6 4 2 10 3 6 4 6 2 8 4 8 4 4 2 12 2 4 6 7 4 8 2 6 4 8 2 12 2 4 6 6 4 8 2 10 5 4 2 12 4 4 4 8 2 12 4 6 4 4 4 12 2 6 6 9
更好的解法
#include <iostream>
#include <memory.h>
using namespace std;
int main() {
int m,n;
cin>>m>>n;
int * prime = new int[n+1];
int *cnt = new int[n+1];
int *fac = new int[n+1];
memset(prime,0,sizeof(int)*(n+1));
memset(cnt,0,sizeof(int)*(n+1));//储存最小因子的个数
memset(fac,0,sizeof(int)*(n+1));//储存因子个数
for(int i=2;i<=n;i++) {
if(!prime[i]) {
prime[++prime[0]] = i;
fac[i] = 2;
cnt[i] = 1;
}
for(int j=1;j<=prime[0];j++) {
if(i*prime[j] > n) break;
prime[i*prime[j]] = 1;
if(i%prime[j]==0) {
fac[i*prime[j]] = fac[i]/(cnt[i]+1)*(cnt[i]+2);
cnt[i*prime[j]] = cnt[i] + 1;
break;
}else {
fac[i*prime[j]] = fac[i]*fac[prime[j]];
cnt[i*prime[j]] = 1;
}
}
}
for(int i=m;i<=n;i++) {
cout<<fac[i]<<"\n";
}
delete[] prime;
delete[] cnt;
delete[] fac;
}