zoukankan      html  css  js  c++  java
  • 数论:素数判定

    数学问题的解决窍门

    • 素数判定

    所谓素数: 指恰好有2个约数的整数。

    判定: 因为n的约数都不超过n, 所以只要检查 2 ~ n-1 的所有整数是否整除n就能判定n是不是素数。

    1. 在此,如果d 是 n的约数, 那么 n/d也是n的约数。由n = d * n / d 可知 min(d, n/d) <= 根号n , 所以只要检查 2 ~ ​ 根号n 的所有整数就足够了。

    2. 同理可知,整数分解和约数枚举都可以在 O(根号n​) 时间完成。(还有更高效的算法)

    #include <iostream>
    #include <map>
    #include <vector>
    using namespace std;
    ​
    //假设输入的都是正数
    //素性测试
    bool is_prime(int n)
    {
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return n != 1;     //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> prime_factor(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;
    } 
    ​
    int main()
    {
        //记住这个就差不多了
        cout << "素性测试: " << is_prime(7) << endl;
        cout << "==================================================
    ";
        
        cout << "约数枚举(约数总数为2,则为素数):
    ";
        vector<int> res = divisor(13);
    //  for (const auto& e : res) {
    //      cout << e << " ";
    //  }   
        cout << (res.size() == 2) << endl;
        cout << "==================================================
    ";
        
        cout << "整数分解(他没有被任何数分解:
    ";
        int n = 19;
        map<int, int> res2 = prime_factor(n);
    //  for (auto it = res2.begin(); it != res2.end(); ++it)
    //  {
    //      cout << it->first << " " << it->second << "   ";
    //      cout << endl;
    //  }
        cout << (res2[n] == 1) << endl;
    ​
        return 0;
    }
    • 诶氏筛法

    如果只对一个整数进行素性测试, 通常 的算法就够了,如果要对许多整数进行素性测试,则有更高效的算法。

    素数的个数

    给定整数n, 请问n以内有多少个素数?

    限制条件:

    • ​n <= 10^6

    #include <iostream>
    using namespace std;
    ​
    const int maxn = 10000000;
    int prime[maxn];              //第i个素数
    bool is_prime[maxn + 1];      //is_prime[i]为true 表示i是素数
    //返回n以内的素数个数
    int sieve(int n)
    {
        int p = 0;                //统计素数的个数
        //初始化
        for (int i = 0; i <= n; i++) {
            is_prime[i] = true;
        }
        is_prime[0] = is_prime[1] = false;
    ​
        for (int i = 0; i <= n; i++) {
            if (is_prime[i]) {
                prime[p++] = i;  //将素数添加到prime中
                //1.首先2是素数, 然后划去所有2的倍数
                //2.表中剩余的最小数字是3, 它不能被更小的数整除, 所以是素数。再将表中所有3的倍数都划去
                //3.依次类推, 如果表中剩余的最小数字是m时, m就是素数。然后将表中所有m的倍数都划去。像这样,就能依次枚举n以内的素数。
                for (int j = 2 * i; j <= n; j += i) {
                    is_prime[j] = false;
                }
            }
        }
        return p;
    }
    ​
    int main()
    {
    ​
        int cnt = sieve(30);
        
        for (int i = 0; i < cnt; i++) 
        {
            cout << prime[i] << " ";
        }
        
        cout << endl;
        
        return 0;
    }
    • 用埃氏素数解决蓝桥杯简单题

    第八届蓝桥杯第二题:


    标题:等差素数列

    2,3,5,7,11,13,....是素数序列。
    类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
    上边的数列公差为30,长度为6。

    2004年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
    这是数论领域一项惊人的成果!

    有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:

    长度为10的等差素数列,其公差最小值是多少?

    注意:需要提交的是一个整数,不要填写任何多余的内容和说明文字。
    #include <iostream>
    using namespace std;
    ​
    const int maxn = 10000000;
    int prime[maxn];              //第i个素数
    bool is_prime[maxn + 1];      //is_prime[i]为true 表示i是素数
    int sieve(int n);
    bool isPrime(int n);
    void solve();
    ​
    //返回n以内的素数个数
    int sieve(int n)
    {
        int p = 0;                //统计素数的个数
        //初始化
        for (int i = 0; i <= n; i++) {
            is_prime[i] = true;
        }
        is_prime[0] = is_prime[1] = false;
    ​
        for (int i = 0; i <= n; i++) {
            if (is_prime[i]) {
                prime[p++] = i;  //将素数添加到prime中
                //1.首先2是素数, 然后划去所有2的倍数
                //2.表中剩余的最小数字是3, 它不能被更小的数整除, 所以是素数。再将表中所有3的倍数都划去
                //3.依次类推, 如果表中剩余的最小数字是m时, m就是素数。然后将表中所有m的倍数都划去。像这样,就能依次枚举n以内的素数。
                for (int j = 2 * i; j <= n; j += i) {
                    is_prime[j] = false;
                }
            }
        }
        return p;
    }
    ​
    //素性测试
    bool isPrime(int n)
    {
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return n != 1;     //1是例外
    }
    ​
    void solve()
    {
        int N = 10000;
        int cnt = sieve(N);
    //  cout << cnt << endl;
        for (int i = 1; i <= N; i++)        //枚举 1~1000的公差 
        {
            for (int j = 0; j < cnt; j++) 
            {
                int flag = 1,       //标志 
                    tmp = prime[j]; //第j个素数
                for (int k = 1; k < 10; k++)   //第一个数已经确定是素数 
                {
                    if (tmp + i > N || !isPrime(tmp + i)) {
                        flag = 0; break;
                    }
                    else {
                        tmp = tmp + i;     //下一个数 
                    }
                }
                //如果 连续9个公差为i的数都是素数 
                if (flag) {
                    cout << i << "  开始的素数:" << prime[j] << endl;
                    return;
                }
            }
        }
    }
    ​
    int main()
    {
        
        solve();
        
        return 0;
    }
    • 练习题

    • POJ 3126: Prime Path

    • POJ 3421: X-factor Chains

    • POJ 3292: Semi-prime HB-numbers

  • 相关阅读:
    转: wireshark过滤规则
    PHP开发
    转:python安装pycrypto
    How to use pycharm to debug scrapy projects
    VCForPython27.msi安装后, 还显示error: Unable to find vcvarsall.bat
    Dcgpofix
    Dsamain
    组托管服务帐户概述
    创建 PSO
    介绍 Active Directory 域服务 (AD DS) 虚拟化
  • 原文地址:https://www.cnblogs.com/douzujun/p/7955764.html
Copyright © 2011-2022 走看看