最小素数和


19

SF(n)是一个函数,用于计算给定数字n的最小素数。

我们称T(N)为每个SF(n)的总和,其中2 <= n <=N。

T(1)= 0(总和超过0)

T(2)= 2(2是第一个素数)

T(3)= 5 = 2 + 3

T(4)= 7 = 2 + 3 + 2

T(5)= 12 = 2 + 3 + 2 + 5

...

T(10000)= 5786451

获胜者将是能够在我自己的笔记本电脑(东芝Satellite L845,Intel Core i5、8GB RAM)上在60秒内计算出最大T(N)的人。


Current top score: Nicolás Siplis - 3.6e13 points - Nim

Pf(2)= 2,Pf(3)= 3,所以,T(3)= 2 + 3 =5。对吗?我确实编写了程序来查找主要因素,但是您能否详细说明当前的要求。谢谢
The Coder 2015年

1
@ToddLehman我正在自己的笔记本电脑(Sony Vaio SVF14A16CLB)中运行每个代码,因此,如果花费的时间少于60秒,则我将增加该数目,而花费的时间会减少。
尼古拉斯Siplis

1
是的,只要它在我自己的计算机上运行并在60秒或更短的时间内输出正确的答案,就可以接受。
尼古拉斯Siplis

1
它有4个线程。
尼古拉斯Siplis

1
是否允许第三方图书馆?程序正在创建线程可以吗?
编码员

Answers:


12

尼姆3.6e13

由于内存需求太高,在尝试计算尽可能高的N时,简单筛分并不是最佳答案。这是另一种方法(前几天从Nim开始,对速度和语法一见钟情,欢迎提出任何建议使其更快或更易读!)。

import math
import sequtils
import nimlongint # https://bitbucket.org/behrends/nimlongint/

proc s(n : int) : int128 =
    var x = toInt128(n)
    (x * x + x) div 2 - 1

proc sum_pfactor(N : int) : int128 =    
    var
        root = int(sqrt(float(N)))
        u = newSeqWith(root+1,false)
        cntA,cntB,sumA,sumB = newSeq[int128](root+1)
        pcnt,psum,ret : int128
        interval,finish,d,q,t : int

    for i in 0..root:
        cntA[i] = i-1
        sumA[i] = s(i)

    for i in 1..root:
        cntB[i] = N div i - 1
        sumB[i] = s(N div i)

    for p in 2..root:
        if cntA[p] == cntA[p-1]:
            continue

        pcnt = cntA[p - 1]
        psum = sumA[p - 1]
        q = p * p
        ret = ret + p * (cntB[p] - pcnt)
        cntB[1] = cntB[1] - cntB[p] + pcnt
        sumB[1] = sumB[1] - (sumB[p] - psum) * p
        interval = (p and 1) + 1
        finish = min(root,N div q)

        for i in countup(p+interval,finish,interval):

            if u[i]:
                continue

            d = i * p

            if d <= root:
                cntB[i] = cntB[i] - cntB[d] + pcnt
                sumB[i] = sumB[i] - (sumB[d] - psum) * p
            else:
                t = N div d
                cntB[i] = cntB[i] - cntA[t] + pcnt
                sumB[i] = sumB[i] - (sumA[t] - psum) * p

        if q <= root:
            for i in countup(q,finish-1,p*interval):
                u[i] = true

        for i in countdown(root,q-1):
            t = i div p
            cntA[i] = cntA[i] - cntA[t] + pcnt
            sumA[i] = sumA[i] - (sumA[t] - psum) * p

    sumB[1] + ret

var time = cpuTime()
echo(sum_pfactor(int(3.6e13))," - ",cpuTime() - time)

我尝试将Nim的GMP包装器实现到我的代码中,但无法使其工作(以前从未使用过GMP,因此肯定没有帮助)。
尼古拉斯Siplis

您也不需要returnin f的定义。单表达式procs自动返回。
kirbyfan64sos

3
这不是Nim以明显的优势赢得的第一个最快的代码。可能值得调查。
primo

我很好奇它在使用GMP时的性能,但是尽管我付出了很多努力却无法正确实现。
尼古拉斯Siplis

Nim肯定会列入我的学习清单!
Sp3000

5

C,Prime Sieve:5e9

结果:

$ time ./sieve 
Finding sum of lowest divisors of n = 2..5000000000
572843021990627911

real    0m57.144s
user    0m56.732s
sys 0m0.456s 

程序:

尽管它是一个相当简单的程序,但花了我一段时间才弄清楚如何正确地进行内存管理-我在该范围内每个数字只有足够的ram内存,可以容纳每个字节1个字节,因此我必须小心。这是Erasthones的标准筛。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<assert.h>

#define LIMIT ((unsigned long long)5e9 +1)
#define ROOT_LIMIT floor(sqrt(LIMIT))

int main()
{
    printf("Finding sum of lowest divisors of n = 2..%llu\n", LIMIT - 1);
    char * found_divisor;
    found_divisor = malloc(LIMIT * sizeof(char));
    if (found_divisor == NULL) {
        printf("Error on malloc");
        return -1;
    }
    unsigned long long i;
    unsigned long long trial_div;
    unsigned long long multiple;
    unsigned long long sum = 0;

    for (i = 0; i < LIMIT; ++i) {
        found_divisor[i] = 0;
    }

    for (trial_div = 2; trial_div <= ROOT_LIMIT; ++trial_div) {
        if (found_divisor[trial_div] == 0) {
            for (multiple = trial_div * trial_div; multiple < LIMIT; multiple += trial_div) {
                if (found_divisor[multiple] == 0) {
                    found_divisor[multiple] = 1;
                    sum += trial_div;
                }
            }
        }
    }

    for (i = 2; i < LIMIT; ++i) {
        if (found_divisor[i] == 0) {
            sum += i;
        }
    }

    free(found_divisor);
    printf("%lld\n", sum);
    return 0;
}

1
如果需要考虑存储,则每个数字一位就足够了。您可以使用位掩码来存储标志。
Reto Koradi 2015年

@RetoKoradi不幸的是,这可能会使程序速度降低到足以使其超过1分钟的时间。
isaacg

您需要assert.h做什么?
Max Ried

@MaxRied它是早期版本的遗留物。
isaacg 2015年

3

Perl,蛮力分解

use ntheory ":all";
sub T {
  my $sum=0;
  for (1..$_[0]) {
    $sum += !($_%2) ? 2 : !($_%3) ? 3 : !($_%5) ? 5 : (factor($_))[0];
  }
  $sum
}
T(90_000_000);

我可以在25秒内在Linux机器上达到大约9e7。深入研究C代码可能会更快,就像在检查2/3/5之后说的那样,完全考虑了这个数字。

使用筛分的方法还有很多聪明的方法。我认为简单的暴力破解方式将是一个开始。顺便说一句,这基本上是欧拉计划问题521。


如果要知道所有有用的信息,在带有筛网的Python中,我只能管理T(47000)。我将尝试类似于您正在执行的操作,以查看是否更快。
卡德,2015年

似乎不使用筛子的速度更快。.我能够使用与您类似的方法来计算T(493900)。
卡德,2015年

以前从未使用过Perl,但我设法验证了您的答案,我将把您添加到列表中!
尼古拉斯Siplis

公平地讲,这使用了我的模块来执行C分解(您可以强制它对所有内容都使用纯Perl,但是当然速度并不快)。
DanaJ

可以使用任何语言组合来计算答案,这样就可以了。
尼古拉斯Siplis

3

开始,21e9

进行筛查以查找每个数字<= N的最小因数。生成goroutine来对数字空间的部分进行计数。

运行“开始运行prime.go -P 4 -N 21000000000”。

package main

import (
    "flag"
    "fmt"
    "runtime"
)

const S = 1 << 16

func main() {
    var N, P int
    flag.IntVar(&N, "N", 10000, "N")
    flag.IntVar(&P, "P", 4, "number of goroutines to use")
    flag.Parse()
    fmt.Printf("N = %d\n", N)
    fmt.Printf("P = %d\n", P)
    runtime.GOMAXPROCS(P)

    // Spawn goroutines to check sections of the number range.
    c := make(chan uint64, P)
    for i := 0; i < P; i++ {
        a := 2 + (N-1)*i/P
        b := 2 + (N-1)*(i+1)/P
        go process(a, b, c)
    }
    var sum uint64
    for i := 0; i < P; i++ {
        sum += <-c
    }
    fmt.Printf("T(%d) = %d\n", N, sum)
}

func process(a, b int, res chan uint64) {
    // Find primes up to sqrt(b).  Compute starting offsets.
    var primes []int
    var offsets []int
    for p := 2; p*p < b; p++ {
        if !prime(p) {
            continue
        }
        primes = append(primes, p)
        off := a % p
        if off != 0 {
            off = p - off
        }
        offsets = append(offsets, off)
    }

    // Allocate sieve array.
    composite := make([]bool, S)

    // Check factors of numbers up to b, a block of S at a time.
    var sum uint64
    for ; a < b; a += S {
        runtime.Gosched()
        // Check divisibility of [a,a+S) by our set of primes.
        for i, p := range primes {
            off := offsets[i]
            for ; off < S; off += p {
                if composite[off] {
                    continue // Divisible by a smaller prime.
                }
                composite[off] = true
                if a+off < b {
                    sum += uint64(p)
                }
            }
            // Remember offset for next block.
            offsets[i] = off - S
        }
        // Any remaining numbers are prime.
        for i := 0; i < S; i++ {
            if composite[i] {
                composite[i] = false // Reset for next block.
                continue
            }
            if a+i < b {
                sum += uint64(a + i)
            }
        }
    }
    res <- sum
}

func prime(n int) bool {
    for i := 2; i*i <= n; i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}

请注意,N = 21e9的答案在2 ^ 63和2 ^ 64之间,因此我必须使用无符号64位整数来正确计数...


我必须对其进行修改才能在我的计算机上运行(将N减少到1e9),但是运行时本身非常快,很好!
尼古拉斯Siplis

@NicolásSiplis:内存使用情况已修复。
基思·兰德尔

运行时间是80秒,但1.6e10几乎是60秒!
尼古拉斯Siplis

2

C ++,1 << 34〜1.7e10

Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz

$ g++ -O2 test3.cpp 
$ time ./a.out 
6400765038917999291

real    0m49.640s
user    0m49.610s
sys 0m0.000s
#include <iostream>
#include <vector>

using namespace std;

const long long root = 1 << 17; // must be a power of two to simplify modulo operation
const long long rootd2 = root >> 1;
const long long rootd2m1 = rootd2 - 1;
const long long mult = root; // must be less than or equal to root
const long long n = root * mult; // unused constant (function argument)

int main() {
  vector < int > sieve(rootd2, 0);
  vector < int > primes;
  vector < long long > nexts;
  primes.reserve(root);
  nexts.reserve(root);
  // initialize sum with result for even numbers
  long long sum = n / 2 * 2;
  // sieve of Erathosthenes for numbers less than root
  // all even numbers are skipped
  for(long long i = 1; i < rootd2; ++i){
    if(sieve[i]){
      sieve[i] = 0;
      continue;
    }
    const long long val = i * 2 + 1;
    primes.push_back(val);
    sum += val;
    long long j;
    for(j = (val + 1) * i; j < rootd2; j += val){
      sum += val * (1 - sieve[j]); // conditionals replaced by multiplication
      sieve[j] = 1;
    }
    nexts.push_back(j);
  }
  int k = primes.size();
  long long last = rootd2;
  // segmented sieve of Erathosthenes
  // all even numbers are skipped
  for(int segment = 2; segment <= mult; ++segment){
    last += rootd2;
    for(int i = 0; i < k; ++i){
      long long next = nexts[i];
      long long prime = primes[i];
      if(next < last){
        long long ptr = next & rootd2m1; // modulo replaced by bitmasking
        while(ptr < rootd2){
          sum += prime * (1 - sieve[ptr]); // conditionals replaced by multiplication
          sieve[ptr] = 1;
          ptr += prime;
        }
        nexts[i] = (next & ~rootd2m1) + ptr;
      }
    }
    for(int i = 0; i < rootd2; ++i){
      sum += ((segment - 1) * root + i * 2 + 1) * (1 - sieve[i]);
      sieve[i] = 0;
    }
  }
  cout << sum << endl;
}

2

Java 8:1.8e8 2.4e8

此项与其他已经存在的其他项没有比较,但是我想发表自己的回答,因为我很乐于从事此工作。

我的方法的主要优化如下:

  • 每个偶数的最小因子为2,因此在处理每个奇数后可以免费添加这些因子。基本上,如果您已经完成了计算T(N)时间的工作N % 2 == 1,就知道T(N + 1) == T(N) + 2。这使我可以从3开始计数,并以2为增量递增。
  • 我将质数存储在数组中而不是Collection类型中。这是N我可以达到的两倍以上。
  • 我使用质数来分解数字,而不是执行Eratosthenes筛分法。这意味着我的内存存储几乎完全限于我的素数阵列。
  • 我存储了要寻找最小因子的数字的平方根。我每次都尝试使用@ user1354678求平方一个素数的方法,但是从我的得分来看,这花费了我不到1e7。

这就是全部。我的代码从3开始迭代两次,直到检测到达到或超过时间限制为止,然后才吐出答案。

package sum_of_smallest_factors;

public final class SumOfSmallestFactors {
    private static class Result {
        private final int number;
        int getNumber() {
            return number;
        }

        private final long sum;
        long getSum() {
            return sum;
        }


        Result(int number, long sum) {
            this.number = number;
            this.sum = sum;
        }
    }


    private static final long TIME_LIMIT = 60_000_000_000L; // 60 seconds x 1e9 nanoseconds / second


    public static void main(String[] args) {
        SumOfSmallestFactors main = new SumOfSmallestFactors();
        Result result = main.run();
        int number = result.getNumber();
        long sum = result.getSum();
        System.out.format("T(%,d) = %,d\n", number, sum);
    }


    private int[] primes = new int[16_777_216];
    private int primeCount = 0;
    private long startTime;


    private SumOfSmallestFactors() {}

    private Result run() {
        startClock();
        int number;
        long sumOfSmallestFactors = 2;
        for (number = 3; mayContinue(); number += 2) {
            int smallestFactor = getSmallestFactor(number);
            if (smallestFactor == number) {
                addPrime(number);
            }
            sumOfSmallestFactors += smallestFactor + 2;
        }
        --number;

        Result result = new Result(number, sumOfSmallestFactors);
        return result;
    }

    private void startClock() {
        startTime = System.nanoTime();
    }

    private boolean mayContinue() {
        long currentTime = System.nanoTime();
        long elapsedTime = currentTime - startTime;
        boolean result = (elapsedTime < TIME_LIMIT);
        return result;
    }

    private int getSmallestFactor(int number) {
        int smallestFactor = number;
        int squareRoot = (int) Math.ceil(Math.sqrt(number));

        int index;
        int prime = 3;
        for (index = 0; index < primeCount; ++index) {
            prime = primes[index];

            if (prime > squareRoot) {
                break;
            }

            int remainder = number % prime;
            if (remainder == 0) {
                smallestFactor = prime;
                break;
            }
        }

        return smallestFactor;
    }

    private void addPrime(int prime) {
        primes[primeCount] = prime;
        ++primeCount;
    }
}

在最新版本的Java 8上运行于不同的系统(Windows 8.1,Intel core i7 @ 2.5 GHz,8 GB RAM)上时,无需更改代码即可获得明显更好的结果:

T(240,308,208) = 1,537,216,753,010,879

如果您可以仅通过简单的条件替换mayContinue()in for loop condition,就可以达到更高的效果。我喜欢您预先计算偶数和然后加2的方法。
编码员

@ user1354678,感谢您的推荐。奇怪的是,它没有用。我在另一台计算机上尝试了此代码的变体,发现发布的版本是最快的版本。从代码中删除时钟调用并使用简单的阈值数字花费了我一秒钟多的时间。我什至尝试将我切换startTime到,endTime以消除〜2e7的减法,但是这使我的分数损失了3e7!
sadakatsu

您是否尝试过使用它System.nanoTime() - startTime < TIME_LIMIT,因为它对我来说将您的代码固定了一点。考虑到事实,这种情况已被检查了无数次,所以速度不是很快。有一两件事我从你的代码了解到的情况是,不要把for里面for..后移动for到另一个方法在我的代码,我的代码的运行速度得到提高40%,谢谢..有一件事我还是搞清楚是,没阵列考虑到一个事实,它是赚得了数百万的时候,比ArrayList的多效...
编码器

x2如果执行,就可以达到结果MultiThreading。但是,在运行Prime计算之前,需要预先计算整个数组。
编码员

@ user1354678,将检查从mayContinue()方法中移到for循环中会使我的得分降低8e6。这可能是局部优化的问题。在开发此解决方案时,我尝试了几种用于存储素数的数据类型。我只能通过达到8.8e7 ArrayList,但使用数组达到了1.8e8(现在为2.4e8)。查找可能会带来一些性能提升,但是内存分配会明显提高。我曾考虑过对算法进行多线程处理,但是遇到了问题。
sadakatsu

1

R,2.5e7

简单的Eratosthenes筛子,尽可能地矢量化。R并不是真正针对此类问题设计的,我很确定它可以做得更快。

MAX <- 2.5e7
Tot <- 0
vec <- 2:MAX 
while(TRUE) {
    if (vec[1]*vec[1] > vec[length(vec)]) {
        Tot <- Tot + sum(as.numeric(vec))
        break
    }

    fact <- which(vec %% vec[1] == 0)
    Tot <- Tot + vec[1]*length(vec[fact])
    vec <- vec[-fact]
}
Tot

关于T的公平点。2:MAX是整数的向量,因此对于较大的MAX值,sum(vec)导致整数溢出并返回NA。 sum(as.numeric(vec))正在求和一个不会溢出的双精度向量(尽管它可能无法给出正确的答案)
哇哇(Mawir

1

Python,〜7e8

使用递增的依兰亭烯筛。确实需要注意用最小除数标记标记值,但是在其他方面实现起来相当简单。

使用PyPy 2.6.0进行计时,输入被接受为命令行参数。

from sys import argv
from math import sqrt

n = int(argv[1])
sieve = {}
imax = int(sqrt(n))

t = n & -2
i = 3
while i <= n:
  divs = sieve.pop(i, [])
  if divs:
    t += divs[-1]
    for v in divs:
      sieve.setdefault(i+v+v, []).append(v)
  else:
    t += i
    if i <= imax: sieve[i*i] = [i]
  i += 2

print t

样品用量

$ pypy sum-lpf.py 10000
5786451

$ pypy sum-lpf.py 100000000
279218813374515

0

朱莉娅(5e7)

朱莉娅当然可以做得更好,但这就是我现在所拥有的。这在JuliaBox上大约60秒内完成5e7,但是我还不能在本地测试。希望届时我会想到一种更聪明的方法。

const PRIMES = primes(2^16)

function lpf(n::Int64)
    isprime(n) && return n
    for p in PRIMES
        n % p == 0 && return p
    end
end

function T(N::Int64)
    local x::Int64
    x = @parallel (+) for i = 2:N
        lpf(i)
    end
    x
end

在这里,我们正在创建一个函数lpf,该函数迭代顺序的质数,并检查每个输入的可除性。该函数返回遇到的第一个除数,从而获得最小素数。

主函数lpf并行计算2到输入的整数,并通过求和来减少结果。


0

普通Lisp,1e7

(defvar input 10000000)
(defvar numbers (loop for i from 2 to input collect i))
(defvar counter)
(defvar primes)

(setf primes (loop for i from 2 to (floor (sqrt input))
    when (loop for j in primes
        do (if (eq (mod i j) 0) (return nil))
        finally (return t))
    collect i into primes
    finally (return primes)))

(format t "~A~%"    
    (loop for i in primes
        do (setf counter 0)
        summing (progn (setf numbers (remove-if #'(lambda (x) (if (eq (mod x i) 0) (progn (incf counter) t))) numbers))
                (* i counter)) into total
        finally (return (+ total (reduce #'+ numbers)))))

我选择先生成一个从2到的质数列表(sqrt input),然后用质数测试每个值,而以前我会针对直到的每个数字进行测试(sqrt input),这将毫无意义(例如,如果一个数字可以被4整除,也可以被2整除,因此已经被考虑了。)

感谢上帝在我这样做时的副作用。remove-if既减小了列表的大小,又计算了删除的元素数量,所以我只需要将该值乘以循环所处的值,然后将其添加到运行的总数中即可。

(有趣的事实:delete是的破坏性等效项remove,但无论出于何种原因,deleteremove这种情况都要慢得多。)


以前从未使用过Lisp,尝试运行您的代码时遇到编译器错误:(defvar total 0)(defvar counter 0)(defvar input 10000)(defvar number(i从2循环到输入collection i))( i从2到(地板(sqrt输入))(setf计数器0)的循环求和(prog2(nsubstitute-if 0#'(lambda(x)(if(eq(mod xi))0)(progn(incf counter)t) )))数字)(* i计数器)(setf数字(删除0数字)))最后总计(返回(+ total(减少#'+数字))))
NicolásSiplis 2015年

我正在使用SBCL 1.0.38,但是当我回到家时,我将更新为最新版本,并查看进展情况。如果将其保存到文件中,则可以使用“ sbcl --script <文件名>”运行它。
蜡烛

我尝试过但还是没有运气,以防万一我尝试与Ideone在线进行编译,但是那也不起作用。
尼古拉斯Siplis

哦,对不起,我忘记了第6行的“ do”关键字。不过,它现在应该运行,再试一次。
蜡烛,2015年

太好了,它可以在我的机器上60秒内计算出6e6!顺便说一句,如果我决定输入自己的验证码,您知道我是否应该将其作为答案提交吗?我不确定是否允许新的提交。
尼古拉斯Siplis

0

锈1.5e9

一个非常幼稚的Eratosthene筛子,但我觉得Rust在这里没有得到任何爱!

// Expected (approximate) number of primes
fn hint(n:usize) -> usize {
    if n < 2 { 
        1
    } else {
        n / ((n as f64).ln() as usize) + 1
    }
}

fn main() {
    let n:usize = match std::env::args().nth(1) {
        Some(s) => s.parse().ok().expect("Please enter a number !"),
        None => 10000,
    };
    let mut primes = Vec::with_capacity(hint(n));
    let mut sqrt = 2;
    let s = (2..).map(|n:u32| -> u32 {
        if (sqrt * sqrt) < n {
            sqrt += 1;
        }
        let (div, unseen) = match primes.iter().take_while(|&p| *p <= sqrt).filter(|&p| n % p == 0).next() {
            Some(p) => (*p, false),
            None => (n, true),
        };
        if unseen {
            primes.push(div);
        }
        div
    }).take(n-1).fold(0, |acc, p| acc + p);
    println!("{}", s);
}

0

Java 2.14e9

利用BitSet的纯Eratosthenes筛

我计算出的最小素数因子总和Integer.MAX_VALUE - 1仅为33.89 s。但是我不能再做任何大的修改了,因为任何进一步的修改都会导致位集大小的整数溢出。因此,我正在为下一组范围创建另一个位集。在那之前,这是我能够产生的最快的速度。


T(214,74,83,646) = 109931450137817286 in 33.89 s
aka
T(2,147,483,646) = 109931450137817286 in 33.89 s

import java.util.BitSet;

public class SmallPrimeFactorSum {

    static int    limit     = Integer.MAX_VALUE - 1;

    // BitSet is highly efficient against boolean[] when Billion numbers were involved
    // BitSet uses only 1 bit for each number
    // boolean[] uses 8 bits aka 1 byte for each number which will produce memory issues for large numbers
    static BitSet primes    = new BitSet(limit + 1);
    static int    limitSqrt = (int) Math.ceil(Math.sqrt(limit));

    static long   start     = System.nanoTime();

    static long   sum       = 0;

    public static void main(String[] args) {
        genPrimes();
    }

    // Generate Primes by Sieve of Eratosthenes
    // Sieve of Eratosthenes is much efficient than Sieve of Atkins as
    // Sieve of Atkins involes Division, Modulus, Multiplication, Subtraction, Addition but
    // Sieve of Eratosthenes involves only addition
    static void genPrimes() {

        // Inverse the Bit values
        primes.flip(0, limit + 1);

        // Now all Values in primes will now be true,
        // True  represents     prime number 
        // False represents not prime number

        // Set 0 and 1 as not Prime number
        primes.clear(0, 2);

        // Set all multiples of each Prime as not Prime;
        for ( int prime = 2; prime > 0 && prime <= limit && prime > 0; prime = primes.nextSetBit(prime + 1) ) {
            // Add Current Prime as its Prime factor
            sum += prime;
            // Skip marking if Current Prime > SQRT(limit)
            if ( prime > limitSqrt ) {
                continue;
            }
            // Mark Every multiple of current Prime as not Prime
            for ( int multiple = prime + prime; multiple <= limit && multiple > 0; multiple += prime ) {
                // Mark as not Prime only if it's true already
                if ( primes.get(multiple) ) {
                    // Add Current Prime as multiple's Prime factor
                    sum += prime;
                    primes.clear(multiple);
                }
            }
        }

        System.out.printf("T(%d) = %d in %.2f s", limit, sum, (System.nanoTime() - start) / 1000000000.0);
        //System.out.printf("Total Primes upto %d : %d\n", limit, primes.cardinality());
    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.