zoukankan      html  css  js  c++  java
  • 【数学】素数筛和线性筛

    方法一:暴力

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

    include<stdio.h>
    int is_prime(int x)
    {
        for (int i=2; i*i < x; i++)
            if (x % i == 0)return 0;
        return 1;
    }
    int main()
    {
        int num,prime_num = 0;
        for (num = 1; prime_num<= 1001;)
        {
            num++;
            prime_num += is_prime(num);
        }
        printf("%d
    ",num);
        return 0;
    }
    

    方法二:素数筛

    时间复杂度O(n * sqrt(loglogn))

    总体思想:素数的倍数一定是合数,用已知的素数标记合数

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX_N 1000
    int prime[MAX_N + 5] = {0};
    
    int main()
    {
    
       for (int i = 2; i <= MAX_N; i++){
        if (!prime[i]){
            for (int j = 2*i; j<MAX_N; j += i){
                prime[j] = 1;
            }
        }
       }
       for (int i = 2; i <= MAX_N; i++)
            if(!prime[i]) prime[++prime[0]] = i;
       int n;
       while (~scanf("%d",&n))
       {
           printf("第%d个素数是%d
    ",n,prime[n]);
       }
    }
    

    变形一:求1-1000内每个数字最小的素因子

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX_N 1000
    int prime[MAX_N + 5] = {0};
    
    int main()
    {
    
       for (int i = 2; i*i <= MAX_N; i++){
        if (!prime[i]){
            for (int j = i; j <= MAX_N; j += i){
                if (!prime[j]) prime[j] = i; ///只有第一次赋值,保证最小
            }
        }
       }
    
       int n;
       while (~scanf("%d",&n))
       {
           printf("%d的最小素因子是%d
    ",n,prime[n]);
       }
    }
    

    变形·二:求1-1000内每个数字最大的素因子

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX_N 1000
    int prime[MAX_N + 5] = {0};
    
    int main()
    {
    
       for (int i = 2; i*i <= MAX_N; i++){
        if (!prime[i]){
            for (int j = i; j <= MAX_N; j += i){
                prime[j] = i;/// 覆盖
            }
        }
       }
    
       int n;
       while (~scanf("%d",&n))
       {
           printf("%d的最大素因子是%d
    ",n,prime[n]);
       }
    }
    

    方法三:线性筛

    时间复杂度O(n )

    总体思想:

    线性筛是基于素数筛的改进,
    在素数筛的时候
    6被2标记后,又被3标记...
    15被3标记后,又被5标记...
    30被2标记后,又被3标记,又又被5标记...
    会有重复标记造成的浪费
    线性筛的时候

    M              为遍历数的代表
    Min_p (M)       为M的最小素因子
    Set_p (n)      为从2到n的素数集合
    

    第一层循环是:遍历M
    第二层循环是:遍历这个Set_p (Min_p (M))的集合元素
    eg:
    M == 15
    Min_p (M) == 3
    Set_p (Min_p (M)) = {2,3}
    标记的数为:30,45
    75 会是 它最小的素因子5 在M为25 时标记到的

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX_N 000
    int set_prime[MAX_N + 5] = {0};
    
    int main()
    {
    
        for (int m = 2; m <= MAX_N; m++)
        {
            if (!set_prime[m]) set_prime[++set_prime[0]] = m;
            for (int j = 1; j <= set_prime[0] && set_prime[j] * m <= MAX_N; j++)
            {
                set_prime[set_prime[j] * m] = 1;
                if (m % set_prime[j] == 0) break;///功能:保持 prime[j]  一定小于 i 的最小素因子
            }
        }
        int n;
        while (~scanf("%d",&n))
        {
            printf("第%d个的素数是%d
    ",n,set_prime[n]);
        }
    }
    
  • 相关阅读:
    洛谷 P2616 [USACO10JAN]购买饲料II Buying Feed, II
    洛谷 P3654 First Step (ファーストステップ)
    洛谷 P1223 排队接水
    洛谷 【P1252】马拉松接力赛
    codevs 4927 线段树练习5
    洛谷 P1678 烦恼的高考志愿
    初识 线段树
    开学第一测
    洛谷 P1531 I Hate It
    CSS3 过渡
  • 原文地址:https://www.cnblogs.com/sxy-798013203/p/7790067.html
Copyright © 2011-2022 走看看