【问题标题】:Summing Prime Numbers below two million将低于 200 万的素数相加
【发布时间】:2011-02-26 14:35:13
【问题描述】:

您可能听说过一个名为 Project Euler (projecteuler.net) 的网站。我正在解决第一个问题,这些问题非常简单,我正在解决标题中描述的问题。

这与优化或任何事情无关 - 大约需要千分之 90 秒才能完成。它给了我错误的总数。

有人可以帮助我吗?我不知道为什么我得到的答案——从数组总数(总数)和正常相加的总数(总数)——是不正确的。他们都显示的答案是 947402457,它告诉我的网站是错误的答案。

如果只是措辞,问题就在这里:http://projecteuler.net/index.php?section=problems&id=10

另外很奇怪的是,据我所知,当你可以在最后输入你想查看的素数时(它将它从数组中取出),它会给你正确的答案.

#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <ctime>

typedef unsigned long int bignum;
//there are 666671 primes below two million
int main(){
    using namespace std;
    bignum top = 2000000;
    bignum total = 0;
    bignum atotal = 0;
    //hardcode 2 and 3
    total += 5;
    int inc = 2;
    bignum n = 5;
    double sq = n;
    bignum np = 1;
    bignum *pa = new bignum[top];
    pa[0] = 2;
    pa[1] = 3;
    while (n < top){
        int div = 5;
        int divinc = 2;
        int p = 1;
        //check if number is prime
        //check divisiblity from any possible prime up to the square root of n
        //first hardcode 2 and 3
        if(n%2==0||n%3==0)
            p = 0;
        else{
            while(div<=sqrt(sq)){
                if(n%div==0){
                    p = 0;
                    break;
                }else{
                    div = div + divinc;
                    if(divinc==2) divinc = 4; else divinc = 2;
                }
            }if(p!=0){ //if it's a prime - 0 is not, 1 is prime
                total = total + n;
                np++;
                pa[np] = n;
                //cout << np << " prime number: " << n << endl; //takes too long if it prints everything
            }
        }
        n += inc;
        if(inc==2) inc = 4; else inc = 2;
    }
    for (int c=0;c<=np;c++){
        atotal += pa[c];
    }
    cout << "Total " << top << ": " << total << endl;
    cout << "Array total: " << atotal << endl;
    cout << "Elapsed time: " << clock() << " " << CLOCKS_PER_SEC << "s of a second" << endl << endl;
    while(true){
            int ptoview = 0;
            cout << "Enter the number of the prime you would like to see (you can view every prime number below "<<top<<") ";
            cin >> ptoview;
            if (pa[ptoview-1]){
                if (pa[ptoview-1] < top)
                    cout << ptoview << " prime: " << pa[ptoview-1] << endl;
                else
                    cout << "Too high/low" << endl;
                cout << endl;
            }
        }
    system("PAUSE");
    return 0;
}

【问题讨论】:

  • @Pig Head:您的算法是否适用于小于 2000000 的数字?我的意思是,对于 10、15 或 20。
  • 代码中“//有 666671 个质数低于 200 万”的陈述是完全错误的。事实上,它大约高出 4 倍。
  • 当我运行你的程序时,它说以下是素数:25, 35, 49, 55, 65, ...
  • @wood - 在我的程序实际运行之前,我早就把它放在那里了。 @Blast - 真的吗?我会检查的。
  • @Blast - 这似乎是个问题!我怎么没有注意到我不知道。

标签: c++ primes


【解决方案1】:

这是至少一个问题的线索。看看替换时会发生什么:

for (int c=0;c<=np;c++){
    atotal += pa[c];
}

与:

for (int c=0;c<=np;c++){
    bignum oldatotal = atotal;
    atotal += pa[c];
    if (atotal < oldatotal)
        cout << "Hmmm: " << oldatotal << " " << atotal << endl;
}

我得到类似的东西:

Hmmm: 4294819625 12858
Hmmm: 4294864122 123849
Hmmm: 4294717053 27802
Hmmm: 4294697657 51420
: : :
Hmmm: 4293781002 792849
Hmmm: 4294658253 1676602
Hmmm: 4293686116 710941
Hmmm: 4294706293 1737578
Total 2000000: 947402457
Array total: 947402457

我不会详细介绍,因为这是一个谜题,我假设您希望至少保持一点挑战性 :-)


是的,您是对的(根据您在下面的评论),所以我会让答案变得不那么迟钝,以便对其他人更有用。

unsigned long 类型不够大,无法容纳所有这些素数的总和,所以它会环绕。

它是否可以自己保存实际的素数我没有检查过,但下一段的答案也会解决这个问题。

您可能想尝试将bignum 重新定义为“更大”类型,如unsigned long long(如果可用)。

【讨论】:

  • 这不公平!看 typeof(oldtotal) 是 bignum
  • 我查看了数据类型,发现 long int 的数字接近最大值 - 我将 typedef 更改为 unsigned long long int,它运行良好 - 谢谢!
【解决方案2】:

没有查看所有内容,但 sq 未在主 while 循环中修改。这似乎不对。 (顺便说一句,我会使用筛滤器来获得质数)。

【讨论】:

  • 我本来打算去的,但我没有看到任何意义,因为这已经非常快了。
  • 你是对的,sq 没有被修改,这是问题所在。嗯,一个问题。
猜你喜欢
  • 2013-05-28
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
  • 2018-03-14
  • 2015-07-01
  • 2016-11-30
相关资源
最近更新 更多