ক্ষুদ্রতম মৌলিক কারণগুলির সমষ্টি


19

এসএফ (এন) এমন একটি ফাংশন যা কোনও প্রদত্ত সংখ্যার জন্য ক্ষুদ্রতম মৌলিক গুণককে গণনা করে।

আমরা টি (এন) কে 2 এস = (এন) এর সাথে 2 <= n <= N দিয়ে যোগ করব call

টি (1) = 0 (যোগফল 0 টি শীর্ষের বেশি)

টি (2) = 2 (2 প্রথম প্রধান)

টি (3) = 5 = 2 + 3

টি (4) = 7 = 2 + 3 + 2

টি (5) = 12 = 2 + 3 + 2 + 5

...

টি (10000) = 5786451

বিজয়ী সেই ব্যক্তি হবেন যিনি আমার নিজের ল্যাপটপে (তোশিবা স্যাটেলাইট এল 845, ইন্টেল কোর আই 5, 8 জিবি র‌্যাম) 60 সেকেন্ডে বৃহত্তম টি (এন) গণনা পরিচালনা করে।


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

পিএফ (2) = 2, পিএফ (3) = 3, সুতরাং, টি (3) = 2 + 3 = 5. আমি ঠিক আছি? আমি প্রাথমিক কারণগুলি সন্ধানের জন্য কর্মসূচী করি, তবে আপনি বর্তমানের প্রয়োজনীয়তার বিষয়ে বিস্তারিত বলতে পারেন। আপনাকে ধন্যবাদ
দ্য কোডার

1
@ টডলেহম্যান আমি প্রতিটি ল্যাপটপ নিজের কম্পিউটারে চালিয়ে যাচ্ছি (সনি ভাইও এসভিএফ 14 এ 16 সিএলবি), সুতরাং যদি এটি 60 সেকেন্ডেরও কম সময় নেয় তবে আমি সংখ্যাটি বাড়িয়ে দেব এবং বেশি সময় লাগলে এটি হ্রাস করব।
নিকোলের সিপলিস

1
হ্যাঁ, যতক্ষণ না এটি আমার নিজের মেশিনে চলে এবং answer০ সেকেন্ড বা তারও কম সময়ে সঠিক উত্তরটি আউটপুট করে, এটি গ্রহণযোগ্য।
নিকোলের সিপলিস

1
এটিতে 4 টি থ্রেড রয়েছে।
নিকোলস সিপলিস

1
তৃতীয় পক্ষের গ্রন্থাগারগুলি কি অনুমোদিত? প্রোগ্রামটি থ্রেড তৈরি করছে তা ঠিক আছে?
কোডার

উত্তর:


12

নিম, 3.6e13

মেমরির প্রয়োজনীয়তাগুলি খুব বেশি হয়ে যাওয়ার কারণে সর্বাধিক এন সম্ভাব্য হিসাবে গণনা করার চেষ্টা করার সময় কেবল ছাঁটাই ভাল উত্তর নয়। এখানে একটি পৃথক পদ্ধতি রয়েছে (কয়েকদিন আগে নিমের সাথে শুরু হয়েছিল এবং গতি এবং সিনট্যাক্সের প্রেমে পড়েছেন, এটিকে দ্রুত বা আরও বেশি পাঠযোগ্য করে তোলার জন্য যে কোনও পরামর্শই স্বাগত!)।

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)

আমি নিমের জন্য জিএমপি র‍্যাপারটি আমার কোডটিতে প্রয়োগ করার চেষ্টা করেছি কিন্তু এটি কার্যকর করতে পারিনি (আগে কখনও জিএমপি ব্যবহার করা হয়নি যাতে এটি অবশ্যই সহায়তা করে না)।
নিকোলস সিপলিস

এছাড়াও আপনি প্রয়োজন হবে না returnযে fএর সংজ্ঞা। একক-অভিব্যক্তি প্রকস স্বয়ংক্রিয়ভাবে ফিরে আসে।
kirbyfan64sos

3
এটি কোনও প্রথমতম-কোড নয় যা নিম একটি লক্ষণীয় ব্যবধানে জিতেছে। তদন্ত মূল্যবান হতে পারে।
primo

আমি জিএমপি ব্যবহার করার সময় এটি কীভাবে সম্পাদন করে তা দেখতে আগ্রহী, তবে আমার প্রচেষ্টা সত্ত্বেও এটি সঠিকভাবে প্রয়োগ করতে পারেনি।
নিকোলস সিপলিস

নিম অবশ্যই টু-লার্নিংয়ের তালিকায় চলেছে!
Sp3000

5

সি, প্রাইম চালুনি: 5e9

ফলাফল:

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

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

কার্যক্রম:

এটি একটি বরং দৃa় কর্মসূচির প্রোগ্রাম থাকা সত্ত্বেও, মেমরি পরিচালনাটি কীভাবে সঠিকভাবে পেতে যায় তা নির্ধারণ করতে আমার কিছুটা সময় লেগেছিল - আমার কেবলমাত্র পরিসীমাটিতে প্রতি বাইটে 1 বাইটের জন্য পর্যাপ্ত পরিমাণে র্যাম রয়েছে, তাই আমাকে সতর্কতা অবলম্বন করতে হয়েছিল। এটি ইরস্টোনসের একটি আদর্শ চালনি।

#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
স্মৃতি যদি উদ্বেগের বিষয় থাকে তবে প্রতি সংখ্যায় এক বিটই যথেষ্ট। পতাকাগুলি সংরক্ষণ করতে আপনি একটি বিটমাস্ক ব্যবহার করতে পারেন।
13:48

@ রিটোকোরাদি দুর্ভাগ্যক্রমে, এটি সম্ভবত প্রোগ্রামটি কমিয়ে দেবে এটি 1 মিনিটের ব্যবধানে রাখার জন্য।
isaacg

আপনার কী দরকার?
ম্যাক্স রেড

@ ম্যাক্সরিয়েড এটি একটি আর্লি সংস্করণ থেকে ছেড়ে গেছে।
isaacg

3

পার্ল, ব্রুট ফোর্স ফ্যাক্টরিং

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 সেকেন্ডে প্রায় 9e7 পেতে পারি। এটি সি কোডটিতে খনন করে দ্রুততর হতে পারে, যেমন এটি 2/3/5 এর জন্য একটি চেক পরে বলছে, সম্পূর্ণরূপে সংখ্যাটি ফ্যাক্টর করুন।

সিভিং ব্যবহার করে এটি করার আরও অনেক চতুর উপায় রয়েছে। আমি ভেবেছিলাম একটি সহজ প্রাণবন্ত উপায় একটি সূচনা হবে। এটি মূলত প্রজেক্ট অলারের সমস্যা 521, যাইহোক।


যদি এটি জানতে মোটেও কার্যকর হয় তবে পাইথনে চালুনি দিয়ে আমি কেবল টি (47000) পরিচালনা করতে পারি। এটি দ্রুত হয় কিনা তা দেখার জন্য আমি আপনি যা করছেন তার অনুরূপ কিছু চেষ্টা করতে যাচ্ছি।
কেড

দেখে মনে হচ্ছে একটি চালনী ব্যবহার না করা দ্রুত .. আমি আপনার সাথে অনুরূপ পদ্ধতিতে টি (493900) গণনা করতে সক্ষম হয়েছি।
কেদে

পার্ল এর আগে কখনও ব্যবহার করা হয়নি তবে আমি আপনার উত্তর যাচাই করতে সক্ষম হয়েছি, আমি আপনাকে তালিকায় যুক্ত করব!
নিকোলস সিপলিস

সত্যি কথা বলতে, এটি আমার মডিউলটি ব্যবহার করে যা সিতে ফ্যাক্টরিং করে you
দানাজে

উত্তরগুলির যে কোনও ভাষার সংমিশ্রণটি ব্যবহার করে গণনা করা যায়, তাই ঠিক।
নিকোলস সিপলিস

3

যাও, 21e9

প্রতিটি সংখ্যার নূন্যতম ফ্যাক্টরটি অনুসন্ধান করার জন্য একটি চালনী ব্যবহার করে <= N. সংখ্যা স্পেসের অংশগুলি গণনা করার জন্য গারোটিনগুলি তৈরি করে।

"Go run 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
}

নোট করুন যে এন = 21e9 এর উত্তর 2 ^ 63 এবং 2 ^ 64 এর মধ্যে, সুতরাং আমাকে সঠিকভাবে গণনা করতে স্বাক্ষরবিহীন 64৪-বিট ইনস ব্যবহার করতে হয়েছিল ...


আমার মেশিনে চালানোর জন্য আমাকে এটিকে সংশোধন করতে হয়েছিল (হ্রাস এন থেকে 1e9) তবে রানটাইম নিজেই বেশ দ্রুত, ভাল কাজ!
নিকোলের সিপলিস

@ নিকোলসিসপ্লিস: মেমরির ব্যবহার স্থির করা হয়েছে।
কিথ র্যান্ডাল

রানটাইমটি ছিল 80 সেকেন্ড তবে 1.6e10 গণনা করা হয়েছিল প্রায় হুবুহু 60!
নিকোলস সিপলিস

2

সি ++, 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

জাভা 8: 1.8e8 2.4e8

এই এন্ট্রিটি ইতিমধ্যে থাকা অন্য কয়েকটিটির সাথে তুলনা করে না, তবে আমি আমার উত্তর পোস্ট করতে চেয়েছি কারণ আমি এতে কাজ করতে মজা পেয়েছি।

আমার পদ্ধতির মূল অপ্টিমাইজেশানগুলি নিম্নরূপ:

  • প্রতিটি সমান সংখ্যার 2 এর একটি ক্ষুদ্রতম ফ্যাক্টর থাকে, সুতরাং প্রতিটি বিজোড় সংখ্যা প্রক্রিয়া করার পরে এগুলিতে বিনামূল্যে যোগ করা যায়। মূলত, আপনি নিরূপণ করা কাজ সম্পন্ন করা হয়েছে T(N)যখন N % 2 == 1, আপনি কি জানেন যে T(N + 1) == T(N) + 2। এটি আমাকে আমার গণনা তিনটি থেকে শুরু করতে এবং দ্বিগুণ দ্বারা পুনরাবৃত্তির মাধ্যমে বৃদ্ধি করতে সহায়তা করে।
  • আমি আমার প্রাথমিক সংখ্যাগুলিকে কোনও Collectionধরণের বিপরীতে অ্যারেতে সঞ্চয় করি । এটি দ্বিগুণেরও বেশি Nআমি পৌঁছাতে পারি।
  • আমি মৌলিক সংখ্যাগুলি এরোটোস্টিনিসের চালনা সম্পাদনের বিপরীতে কোনও সংখ্যাকে ফ্যাক্টর হিসাবে ব্যবহার করি। এর অর্থ হ'ল আমার মেমরির সঞ্চয়স্থান আমার প্রাইম অ্যারেতে প্রায় সম্পূর্ণ সীমাবদ্ধ।
  • আমি যে সংখ্যার জন্য ক্ষুদ্রতম ফ্যাক্টরটি অনুসন্ধান করার চেষ্টা করছি তার বর্গক্ষেত্র সংরক্ষণ করি। আমি প্রতিবার একটি প্রধান উপাদানকে স্কোয়ার করার জন্য @ ব্যবহারকারীর 1354678 এর পদ্ধতির চেষ্টা করেছি, তবে এটি আমার স্কোর থেকে প্রায় 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;
    }
}

জাভা 8 এর সর্বশেষ সংস্করণ সহ একটি ভিন্ন সিস্টেমে (উইন্ডোজ 8.1, ইন্টেল কোর আই 7 @ 2.5 গিগাহার্টজ, 8 জিবি র‌্যাম) চালানো কোনও কোড পরিবর্তন ছাড়াই উল্লেখযোগ্যভাবে আরও ভাল ফলাফল করেছে:

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

আপনি প্রতিস্থাপন করতে পারে এমন mayContinue()মধ্যে for loop conditionশুধুমাত্র একটি সহজ শর্তে সঙ্গে, আপনি উচ্চতর ফলাফল অর্জন করতে পারে। এবং আমি আপনার সংক্ষিপ্ত পরিমাণকে পূর্ব অঙ্কের পদ্ধতিটি পছন্দ করি, তারপরে দুটি দ্বারা বৃদ্ধি করা।
কোডার

@ ব্যবহারকারী1354678, সুপারিশের জন্য ধন্যবাদ। আশ্চর্যের বিষয় হল এটি কার্যকর হয়নি। আমি একটি ভিন্ন কম্পিউটারে এই কোডটির বিভিন্নতা চেষ্টা করে দেখেছি যে পোস্ট করা সংস্করণটি সবচেয়ে দ্রুততম one কোড থেকে ক্লক কলগুলি সরিয়ে এবং একটি সরল থ্রেশহোল্ড নম্বর ব্যবহার করা আমার এক সেকেন্ডের চেয়ে একটু বেশি খরচ করে। এমনকি আমি e 2e7 বিয়োগগুলি দূর startTimeকরতে আমার কাছে স্যুইচ করার চেষ্টা করেছি endTime, তবে আমার স্কোর থেকে আমার জন্য 3e7 ব্যয় হয়েছে!
সদাকাতসু

আপনি কি এটি দিয়ে চেষ্টা করেছেন System.nanoTime() - startTime < TIME_LIMIT, এটি আমার জন্য আপনার কোডটি কিছুটা দ্রুত করে। এটি নির্লজ্জভাবে দ্রুত নয়, সত্য বিবেচনা করে, এই অবস্থা কয়েক মিলিয়ন বার যাচাই করা হয়, এটি একটু দ্রুত হবে। আপনার কোড থেকে আমি একটি জিনিস শিখেছি হ'ল এটি একটির forভিতরে রাখবেন না for.. forআমার কোডে অন্য পদ্ধতিতে চলে যাওয়ার পরে আমার কোডের গতি 40% বৃদ্ধি পেয়েছে, ধন্যবাদ .. একটি জিনিস যা আমি এখনও খুঁজে পাচ্ছি তা হ'ল অ্যারে এটি কয়েক মিলিয়ন বার আনা এই সত্যটি বিবেচনা করার সময় অ্যারেলিস্টের চেয়ে অনেক দক্ষ ...
দ্য কোডার

আপনি x2বাস্তবায়ন যদি আপনি ফলাফল অর্জন করতে পারে MultiThreading। তবে প্রাইম ক্যালকুলেশন চালানোর আগে পুরো অ্যারের প্রাক্ক্যালকুলেট করা দরকার।
কোডার

@ ব্যবহারকারী1354678, mayContinue()পদ্ধতিটি থেকে চেকটিকে লুপের জন্য সরানো আমার স্কোর থেকে আমার 8e6 খরচ করে। এটি স্থানীয় অপ্টিমাইজেশনের একটি সমস্যা হতে পারে। আমি যখন এই সমাধানটি বিকাশ করছিলাম তখন আমি প্রাইমগুলি সঞ্চয় করার জন্য বেশ কয়েকটি ডেটা ধরণের পরীক্ষা করেছিলাম। আমি মাত্র 8.8e7 এ পৌঁছাতে সক্ষম হয়েছি ArrayList, তবে আমি অ্যারে ব্যবহার করে 1.8e8 (এখন 2.4e8) দিয়েছি। অনুসন্ধানের সাথে জড়িত কিছু কার্যকারিতা বৃদ্ধি পেতে পারে, তবে মেমরি বরাদ্দের জন্য সুনির্দিষ্ট বর্ধন রয়েছে। আমি অ্যালগরিদমকে মাল্টি-থ্রেডিংয়ের কথা ভেবেছি, তবে আমি সমস্যার মধ্যে পড়েছিলাম।
সদাকাতসু

1

আর, 2.5e7

যতটা সম্ভব ভেক্টরাইজড ইরোটোস্টিনিসগুলির সহজ মনের চালনী। আর এই ধরণের সমস্যার জন্য সত্যই ডিজাইন করা হয়নি এবং আমি নিশ্চিত এটি আরও দ্রুত তৈরি করা যায়।

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

টি। 2 সম্পর্কে ফর্সা পয়েন্ট: ম্যাক্স হল পূর্ণসংখ্যার ভেক্টর তাই ম্যাক্সের বৃহত্তর মানগুলির sum(vec)জন্য একটি পূর্ণসংখ্যার ওভারফ্লোতে বাড়ে এবং এনএ প্রদান করে। sum(as.numeric(vec))ডাবলসের ভেক্টরকে
সংশ্লেষ করছে

1

পাইথন, e 7e8

ইরাথোস্টেনেসের বর্ধিত চালনী ব্যবহার করা। কিছু যত্ন নেওয়া দরকার যে একটি চিহ্নিত মানটিকে তার সর্বনিম্ন বিভাজকের সাথে চিহ্নিত করা হয়, তবে বাস্তবায়ন অন্যথায় মোটামুটি সোজা এগিয়ে।

সময় পাইপাই ২.6.০ সহ নেওয়া হয়েছিল, ইনপুট একটি কমান্ড লাইন আর্গুমেন্ট হিসাবে স্বীকৃত।

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

অবশ্যই জুলিয়া আরও ভাল করতে পারে তবে আমার কাছে এটি এখনই রয়েছে। এটি জুলিয়াবক্সে প্রায় 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যা ক্রমানুসারে প্রাইমগুলির মাধ্যমে পুনরাবৃত্তি করে এবং প্রতিটি দ্বারা বিভাজনের জন্য ইনপুটটি পরীক্ষা করে। ফাংশনটি প্রথম ডিভোজারের মুখোমুখি হয়, যার ফলে সর্বনিম্ন প্রাথমিক উপাদানটি পাওয়া যায়।

প্রধান ফাংশনটি lpf2 থেকে ইনপুটে সমান্তরালে ইনপুটগুলিতে গণনা করে এবং সমষ্টি দ্বারা ফলাফল হ্রাস করে।


0

কমন লিস্প, 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 দ্বারা বিভাজ্য, সুতরাং এটি ইতিমধ্যে হিসাবে গণ্য করা হয়))

পার্শ্ব প্রতিক্রিয়া থাকাকালীন Godশ্বরের ধন্যবাদ। অপসারণ-যদি উভয়ই তালিকার আকার হ্রাস করে এবং কতগুলি উপাদান অপসারণ করা হয়েছে তা গণনা করে, তাই আমাকে কেবল লুপটি যে পরিমাণ মান অনুসারে গুনতে হবে এবং চলমান মোটের সাথে এটি যোগ করতে হবে।

(মজাদার ঘটনা: deleteএর ধ্বংসাত্মক সমতুল্য remove, তবে যে কারণেই হোক না কেন, এই ক্ষেত্রেের deleteচেয়ে সব ধরণের ধীর হয় remove))


এর আগে কখনও লিস্প ব্যবহার করা হয়নি, আপনার কোড চালানোর চেষ্টা করার সময় আমি একটি সংকলক ত্রুটি পেয়েছি: (ডিফভার মোট 0) (ডিফভার কাউন্টার 0) (ডিফভার ইনপুট 10000) (ডিফভার সংখ্যা (2 থেকে ইনপুট সংগ্রহের জন্য আমি লুপ)) ( আমি লুপটি 2 থেকে (ফ্লোর (স্কয়ার্ট ইনপুট)) (সেটফ কাউন্টার 0) সমষ্টি (প্রগ 2 (এসবিস্টিটি-যদি 0 # '(লাম্বদা (এক্স)) (যদি (একা (মোড এক্স)) 0) (প্রগন (ইনফের কাউন্টার) টি ))) সংখ্যা) (* আমি পাল্টা) (সেট্ফ সংখ্যা (০ সংখ্যাগুলি সরান)) শেষ অবধি (রিটার্ন (+ মোট (কমিয়ে # '+ সংখ্যা))))
নিকোলস সিপলিস

আমি এসবিসিএল ১.০.৩৮ ব্যবহার করছি তবে আমি বাড়ি এলে আমি সর্বশেষতম সংস্করণে আপডেট করব এবং এটি কীভাবে হয় তা দেখুন। আপনি যদি এটি কোনও ফাইলে সংরক্ষণ করেন তবে আপনি এটি "এসবিসিএল - স্ক্রিপ্ট <ফাইল নাম>" দিয়ে চালাতে পারেন।
মোমবাতি

আমি চেষ্টা করেছি কিন্তু এখনও ভাগ্য হয়নি, আমি যদি আইডিয়নের সাথে অনলাইনে সংকলন করার চেষ্টা করেছি তবে এটি কার্যকর হয়নি।
নিকোলস সিপলিস

ওহ, দুঃখিত, আমি line লাইনে "কর" কীওয়ার্ডটি ভুলে গেছি। এটি এখন চালানো উচিত, অন্য শট দিন।
মোমবাতি

দুর্দান্ত, এটি আমার মেশিনে 60 সেকেন্ডে 6e6 গণনা করে! যাইহোক, আমি যদি নিজের কোডটি প্রবেশ করার সিদ্ধান্ত নিই, তবে আপনি কি জানেন যে এটি উত্তর হিসাবে জমা দিতে হবে কিনা? আমি নিশ্চিত নই যে এটি নতুন জমা দেওয়ার অনুমতি দেবে কিনা।
নিকোলস সিপলিস

0

মরিচা 1.5e9

খুব নিষ্পাপ ইরাতোস্টেনের চালুনি, তবে আমি অনুভব করেছি যে মরিচ এখানে কোন ভালবাসা পায় নি!

// 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

জাভা 2.14e9

বিটসেটের সুবিধা সহ ইরোটোস্টিনিসের খাঁটি চালনা S

আমি ক্ষুদ্রতম প্রাইম ফ্যাক্টারের যোগফলটি 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());
    }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.