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

  • 相关阅读:
    韩式英语
    Daily dictation 听课笔记
    words with same pronunciation
    you will need to restart eclipse for the changes to take effect. would you like to restart now?
    glottal stop(britain fountain mountain)
    education 的发音
    第一次用Matlab 的lamada语句
    SVN的switch命令
    String的split
    SVN模型仓库中的资源从一个地方移动到另一个地方的办法(很久才解决)
  • 原文地址:https://www.cnblogs.com/douzujun/p/7955764.html
Copyright © 2011-2022 走看看