无法理解代码背后的逻辑,这是一个在两个给定数之间产生质数的优化问题。

问题描述 投票:0回答:1

彼得想为他的密码系统生成一些质数。请帮助他 你的任务是在两个给定的数字之间生成所有的质数。

输入输入以单行中的测试案例数t开始(t<=10)。在接下来的t行中,每一行都有两个数字m和n(1 <=m <=n <=1000000000, n-m<=100000),用空格隔开。

输出对于每一个测试案例,打印所有素数p,使m <=p <=n,每行一个数字,测试案例用空行隔开。

例子输入:m <=p <=n,一个数字行,测试案例用空行隔开。

2
1 10
3 5

输出:

2
3
5
7

3
5

警告:大的输入输出数据,对某些语言要小心(虽然如果算法设计得好,大多数应该没问题)

我在google上查了一下,找到了上述问题的优化方案,这是代码。

#include <iostream>
#include <cmath>
#include <vector>
#include <set>
using namespace std;

int main() {
    vector<int> primes;
    primes.push_back(2);

    for (int i = 3; i <= 32000; i+=2) {
        bool isprime = true;
        int cap = sqrt(i) + 1;

        vector<int>::iterator p;
        for (p = primes.begin(); p != primes.end(); p++) {
            if (*p >= cap) break;
            if (i % *p == 0) {
                isprime = false;
                break;
            }
        }
        if (isprime) primes.push_back(i);
    }

    int T,N,M;

    cin >> T;

    for (int t = 0; t < T; t++) {
        if (t) cout << endl;

        cin >> M >> N;
        if (M < 2) M = 2;

        int cap = sqrt(N) + 1;

        set<int> notprime;
        notprime.clear();

        vector<int>::iterator p;
        for (p = primes.begin(); p != primes.end(); p++) {

            if (*p >= cap) break;
            int start;

            if (*p >= M) start = (*p)*2;
            else start = M + ((*p - M % *p) % *p); //not able to understand this logic.

            for (int j = start; j <= N; j += *p) {
                notprime.insert(j);
            }
        }

        for (int i = M; i <= N; i++) {
            if (notprime.count(i) == 0) {
                cout << i << endl;
            }
        }

    }
    return 0;
}

我无法理解上面的代码。请大家帮我理解一下。我就是不明白这个程序背后的逻辑(我知道STL,只是想了解一下逻辑)。

c++ stl
1个回答
0
投票

它真的很简单。你预先计算所有存在于你的范围内的质数。然后对于每个质数的倍数,除了第一个,你标记为 "非质数"。

你标记的行只是计算特定质数的倍数在M到N范围内的第一次出现。

编辑:更多解释。

这个方法通过首先搜索所有非质数来找到质数。剩下的就是质数.

要做到这一点,第一步它计算所有 "小 "质数。然后,对于每个小质数,它标记了所有符合目标范围的倍数。要做到这一点,你需要首先计算这个质数在你的范围内的首次出现 - 这就是 "start "变量。基本上,它是质数的第一个倍数,>= M.当你有了 "start",你只需将质数加到当前的数字上,就可以标记所有的倍数,直到你达到N。

如果你仍然对 "start "是如何计算的感到困惑,试着想想如何找到 "x",使它成为 "x = A * y "和 "x >= M",在这里你知道A和M,但不知道 "y"。

另外我觉得这个算法可能有错误。因为它应该对 "nonprime "集合中的每个值完成这个循环。但是,如果第一个未计算的质数总是>N,可能就无所谓了。

© www.soinside.com 2019 - 2024. All rights reserved.