zoukankan      html  css  js  c++  java
  • 3. 有关素数的算法

    1. 素性判定:

      质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。

      如果 d 是 n 的约数, 那么 n / d 也是 n 的约数,可知 min (d, n / d) ≤  √n , 那么只要检查 2 ~ √n 的整数即可。同理可知整数分解和约数枚举都可以在 0(√n) 的时间复杂度下完成。

    //素性测试
    bool isPrime (int n) {
        for (int i = 2; i * i <= n; i++)
            if (n % i == 0) 
                return false;
        return n != 1;
    } 
    
    //约数枚举
    vector<int> divisor (int n) {
        vector<int> res;
        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0){
                res.push_back(i);
                if (i != n / i)
                    res.push_back(n / i); 
            }
        }
        return res;
    } 
    
    //整数分解
    map<int, int> primefactor (int n) {
        map<int, int> res;
        for (int i = 2; i * i <= n; i++) {
            while (n % i == 0){
                ++res[i];
                n /= i;
            }
        }
        if (n != 1) res[n] = 1;
        return res;
    } 

    整数分解(integer factorization)又称素因数分解(prime factorization),是将一个正整数写成几个约数的乘积

    整数分解 map里存放的是 n 的素约数。

    2. 埃氏筛法  0(n log log n)

      用来解决 n 以内有多少素数。

      先将 2 到 n 范围内的所有整数打表, 其中最小的 2 是素数。 将表中所有 2 的倍数都划去。表中剩余最小的 3 是素数,再把表中所有 3 的倍数都划去。以此类推, 如果表中剩余的最小数字是 m 时, m 就是素数。 像这样反复操作,就能依次枚举 n 以内的素数。

    int prime[MAX_N];         //第 i 个素数 
    bool isPrime[MAX_N + 1];  // true 表示 i 是素数
    // 返回 n 以内素数的个数
    int sieve (int n) {
        int p = 0;
        fill (isprime, isprime + n, true);
        isPrime[0] = isPrime[1] = false;
        for (int i = 2; i <= n; i++) {
            if (isPrime[i]){
                prime[p++] = i;
                for (int j = 2 * i; j <= n; j += i)
                    isPrime[j] = false;
            }
        }
        return p;
    } 

    3.区间筛法

       区间 [a, b) , b 以内的合数的最小质因数一定不超过 √b 。 也就是说 如果有 √b 以内的素数表, 就可以吧埃氏筛法用在 [ a, b ) 上,也就是说, 先分别做好 [ 2, √b ) 和 [ a, b) 的表, 然后从 [ 2, √b ) 的表中筛得的素数的同时,也将其倍数从 [a, b) 的表中划去, 最后剩下的就是 [a, b) 内的素数。

    typedef long long ll;
    //区间范围[a, b) 
    bool is_prime[MAX_L];
    bool is_prime_small[MAX_SQRT_B];
    
    void segment_sieve(ll a, ll b) {
        for (int i = 0; (ll) i * i < b; i++) is_prime_small[i] = true;
        for (int i = 0; i < b - a; i++) is_prime[i] = true;
        
        for (int i = 2; (ll)i * i < b; i++) {
            if (is_prime_small[i]) {
                //筛(2, sqrt(b) ) 
                for (int j = 2 * i; (ll)j * j < b; j += i)
                    is_prime_small[j] = false;
                //筛 (a, b) 
                for(ll j = max(2LL, (a + i - 1) / i) * i; j < b; j += i)
                    is_prime[j - a] = false;
            }
        }
    }
  • 相关阅读:
    阅读书籍推荐
    lvarchar类型对表结构变更影响
    离职总结 | 如何做个好员工?
    Windows7 general operation/cmd notes
    (转)CONST用法
    Linux多线程的使用一:互斥锁
    hadoop2.5.2学习及实践笔记(六)—— Hadoop文件系统及其java接口
    hadoop2.5.2学习及实践笔记(五)—— HDFS shell命令行常见操作
    hadoop2.5.2学习及实践笔记(四)—— namenode启动过程源码概览
    hadoop2.5.2学习及实践笔记(三)—— HDFS概念及体系结构
  • 原文地址:https://www.cnblogs.com/astonc/p/10657179.html
Copyright © 2011-2022 走看看