素数筛选法和欧拉筛选法

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;
}
相关推荐
©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页