10^12以下素数的和

Sum of prime numbers below 10^12

本文关键字:      更新时间:2023-10-16

如何找到10^12以下所有素数的和?

我使用O(n * log(log(n)))的Eratosthenes筛,但我想要一个算法来更快地计算。

我的代码在4秒内运行10^8,但计算10^12需要很多小时。

这是我的代码:

#include <iostream>
#include <vector>
#include <algorithm>
#define big  long long int
#define ubig unsigned long long  
#define SZ(x) int(x.size())
#define Pb push_back
using namespace std;
const big maxn = 1000 * 1000 + 10;
const big mod = 100000000;
const big Delta = 100000000;
bool s[mod], p[maxn]; 
big b[maxn]; 
vector <big> primes; 
ubig ans = 0, n;
void init_primes () {
    for (big i = 2; i <= 1000 * 1000; i++) {
        if (p[i]) continue;
        primes.Pb(i);
        b[SZ(primes)-1] = primes.back() * primes.back();
        for (big j = i * i; j <= 1000 * 1000; j += i) {
            p[j] = 1;
        }
    }
}
void sieve (big from, big to) {
    cerr << to / mod << " of " << n / mod  << "n" ;
    fill (s,s+mod,0);
    for (big i = 0; i < SZ(primes) && primes[i] <= to; i++) {
        big j = b[i];
        for (; j <= to; j += primes[i]) {
            s[j%mod] = 1;
        }
        if (j >= b[i]) {
            b[i] = j;
        }
    }
    for (big k = 0; k < mod; k++) {
        if (s[k] == 0) {
            ans += from + k;
            // ans %= Delta;
        }
    }
}
int main () {
    init_primes();
    n = 1000ll * 1000 * 1000 * 1000;
    // cin >> n;
    for (big i = 0; i + mod <= n; i += mod) {
        sieve (i,i+mod);
    }
    cout << ans-1 << endl;
}

好久没溢流了!

我看到了两种明显的方法来加快算法的速度。

首先,使用1000 * 1000作为循环的极限。最好只做一次计算:big limit = 1000 * 1000;,并在循环中使用变量limit。根据编译器的不同,每次循环时都可能重复乘法运算。

第二,你的i-loop步进了1。不要那样做。单独处理i=2的情况,然后从i=3开始循环,每次执行2步。这将使外循环的迭代次数减半。为了进一步节省开支,请参阅"车轮分解"方法。

您可能想尝试将p[]设置为位数组,而不是布尔数组,以节省内存使用。您的速度问题可能是由于内存过载和磁盘交换过多造成的。

相关文章:
  • 没有找到相关文章