Hàm tổng tốc độ siêu tốc


22

Mục tiêu rất đơn giản: tính hàm tổng cho càng nhiều số càng tốt trong 10 giâytính tổng các số.

Bạn phải in kết quả của bạn vào cuối và bạn thực sự phải tính toán nó. Không có chức năng tổng số tự động được cho phép, nhưng các thư viện bignum là. Bạn phải bắt đầu từ 1 và đếm tất cả các số nguyên liên tiếp. Bạn không được phép bỏ qua số.

Điểm của bạn là số lượng chương trình của bạn có thể tính trên máy của bạn / bao nhiêu chương trình của tôi có thể tính trên máy của bạn . Mã của tôi là một chương trình đơn giản trong C ++ (tối ưu hóa tắt), hy vọng bạn có thể chạy nó.

Tài sản quan trọng bạn có thể sử dụng!

  • nếu gcd(m,n) = 1, phi(mn) = phi(m) * phi(n)
  • nếu plà số nguyên tố, phi(p) = p - 1(cho p < 10^20)
  • nếu nlà chẵnphi(2n) = 2 phi(n)
  • những người khác được liệt kê trong liên kết đầu tiên

Ma cua toi

#include <iostream>
using namespace std;

int gcd(int a, int b)
{
    while (b != 0)
    {
        int c = a % b;
        a = b;
        b = c;
    }
    return a;
}

int phi(int n)
{
    int x = 0;
    for (int i=1; i<=n; i++)
    {
        if (gcd(n, i) == 1)
            x++;
    }
    return x;
}

int main()
{
    unsigned int sum = 0;
    for (int i=1; i<19000; i++) // Change this so it runs in 10 seconds
    {
        sum += phi(i);
    }
        cout << sum << endl;
        return 0;
}

2
Có lẽ bạn có thể muốn thêm rằng các số đầu vào phải là số nguyên liên tiếp. Nếu không, tôi có thể chỉ muốn tính hàm tổng cho các lũy thừa chỉ có 2.
Howard

Tôi có thể làm 1, 3, 5, 2, 4hay tương tự?
Leaky Nun

Câu trả lời:


14

Nimrod: ~ 38.667 (580.000.000 / 15.000)

Câu trả lời này sử dụng một cách tiếp cận khá đơn giản. Mã sử ​​dụng một rây số nguyên tố đơn giản lưu trữ số nguyên tố có công suất nguyên tố nhỏ nhất trong mỗi khe cho các số tổng hợp (không cho số nguyên tố), sau đó sử dụng lập trình động để xây dựng hàm tổng trên cùng một phạm vi, sau đó tính tổng kết quả. Chương trình dành hầu như toàn bộ thời gian để xây dựng sàng, sau đó tính toán hàm tổng trong một phần nhỏ thời gian. Có vẻ như nó đi xuống để xây dựng một sàng hiệu quả (với một sự thay đổi nhỏ mà người ta cũng phải có thể trích xuất một yếu tố chính cho các số tổng hợp từ kết quả và phải giữ mức sử dụng bộ nhớ ở mức hợp lý).

Cập nhật: Cải thiện hiệu suất bằng cách giảm dung lượng bộ nhớ và cải thiện hành vi bộ đệm. Có thể giảm hiệu năng hơn 5% -10%, nhưng sự gia tăng độ phức tạp của mã không đáng. Cuối cùng, thuật toán này chủ yếu thực hiện nút cổ chai von Neumann của CPU và có rất ít điều chỉnh thuật toán có thể khắc phục điều đó.

Đồng thời cập nhật ước số hiệu năng do mã C ++ không có nghĩa là được biên dịch với tất cả các tối ưu hóa trên và không ai khác làm điều đó. :)

Cập nhật 2: Tối ưu hóa hoạt động sàng để truy cập bộ nhớ được cải thiện. Bây giờ xử lý hàng loạt số nguyên tố nhỏ thông qua memcpy () (~ 5% tăng tốc) và bỏ qua bội số của 2, 3 và 5 khi sàng các số nguyên tố lớn hơn (~ 10% tăng tốc).

Mã C ++: 9,9 giây (với g ++ 4.9)

Mã Nimrod: 9,9 giây (với -d: phát hành, gcc 4.9 phụ trợ)

proc handleSmallPrimes(sieve: var openarray[int32], m: int) =
  # Small primes are handled as a special case through what is ideally
  # the system's highly optimized memcpy() routine.
  let k = 2*3*5*7*11*13*17
  var sp = newSeq[int32](k div 2)
  for i in [3,5,7,11,13,17]:
    for j in countup(i, k, 2*i):
      sp[j div 2] = int32(i)
  for i in countup(0, sieve.high, len(sp)):
    if i + len(sp) <= len(sieve):
      copyMem(addr(sieve[i]), addr(sp[0]), sizeof(int32)*len(sp))
    else:
      copyMem(addr(sieve[i]), addr(sp[0]), sizeof(int32)*(len(sieve)-i))
  # Fixing up the numbers for values that are actually prime.
  for i in [3,5,7,11,13,17]:
    sieve[i div 2] = 0

proc constructSieve(m: int): seq[int32] =
  result = newSeq[int32](m div 2 + 1)
  handleSmallPrimes(result, m)
  var i = 19
  # Having handled small primes, we only consider candidates for
  # composite numbers that are relatively prime with 31. This cuts
  # their number almost in half.
  let steps = [ 1, 7, 11, 13, 17, 19, 23, 29, 31 ]
  var isteps: array[8, int]
  while i * i <= m:
    if result[i div 2] == 0:
      for j in 0..7: isteps[j] = i*(steps[j+1]-steps[j])
      var k = 1 # second entry in "steps mod 30" list.
      var j = 7*i
      while j <= m:
        result[j div 2] = int32(i)
        j += isteps[k]
        k = (k + 1) and 7 # "mod 30" list has eight elements.
    i += 2

proc calculateAndSumTotients(sieve: var openarray[int32], n: int): int =
  result = 1
  for i in 2'i32..int32(n):
    var tot: int32
    if (i and 1) == 0:
      var m = i div 2
      var pp: int32 = 2
      while (m and 1) == 0:
        pp *= 2
        m = m div 2
      if m == 1:
        tot = pp div 2
      else:
        tot = (pp div 2) * sieve[m div 2]
    elif sieve[i div 2] == 0: # prime?
      tot = i - 1
      sieve[i div 2] = tot
    else:
      # find and extract the first prime power pp.
      # It's relatively prime with i/pp.
      var p = sieve[i div 2]
      var m = i div p
      var pp = p
      while m mod p == 0 and m != p:
        pp *= p
        m = m div p
      if m == p: # is i a prime power?
        tot = pp*(p-1)
      else:
        tot = sieve[pp div 2] * sieve[m div 2]
      sieve[i div 2] = tot
    result += tot

proc main(n: int) =
  var sieve = constructSieve(n)
  let totSum = calculateAndSumTotients(sieve, n)
  echo totSum

main(580_000_000)

Sử thi! +1. Nimrod bắt đầu trở nên phổ biến hơn, 3
cjfaure

Chờ đợi. Ái chà. Tôi đang nâng cao câu trả lời khác của bạn. : P
cjfaure

1
Nimrod có phải là con lai giữa Python và C không?
mbomb007

Nimrod gần đây đã được đổi tên thành Nim; trong khi nó mượn kiểu cú pháp của Python, ngữ nghĩa thì khác và không giống như C, nó an toàn cho bộ nhớ (trừ khi bạn sử dụng các tính năng không an toàn) và có bộ sưu tập rác.
Reimer Behrends

9

Java, điểm ~ 24.000 (360.000.000 / 15.000)

Mã java dưới đây thực hiện tính toán hàm tổng và sàng nguyên tố với nhau. Lưu ý rằng tùy thuộc vào máy của bạn, bạn phải tăng kích thước heap ban đầu / tối đa (trên máy tính xách tay khá chậm của tôi, tôi phải tăng lên -Xmx3g -Xms3g).

public class Totient {

    final static int size = 360000000;
    final static int[] phi = new int[size];

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        long sum = 0;

        phi[1] = 1;
        for (int i = 2; i < size; i++) {
            if (phi[i] == 0) {
                phi[i] = i - 1;
                for (int j = 2; i * j < size; j++) {
                    if (phi[j] == 0)
                        continue;

                    int q = j;
                    int f = i - 1;
                    while (q % i == 0) {
                        f *= i;
                        q /= i;
                    }
                    phi[i * j] = f * phi[q];
                }
            }
            sum += phi[i];
        }
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(sum);
    }
}

9

Nimrod: ~ 2.333.333 (42.000.000.000 / 18.000)

Điều này sử dụng một cách tiếp cận hoàn toàn khác với câu trả lời trước đây của tôi. Xem ý kiến ​​để biết chi tiết. Các longintmô-đun có thể được tìm thấy ở đây .

import longint

const max = 500_000_000

var ts_mem: array[1..max, int]

# ts(n, d) is defined as the number of pairs (a,b)
# such that 1 <= a <= b <= n and gcd(a,b) = d.
#
# The following equations hold:
#
# ts(n, d) = ts(n div d, 1)
# sum for i in 1..n of ts(n, i) = n*(n+1)/2
#
# This leads to the recurrence:
# ts(n, 1) = n*(n+1)/2 - sum for i in 2..n of ts(n, i)
#
# or, where ts(n) = ts(n, 1):
# ts(n) = n*(n+1)/2 - sum for i in 2..n of ts(n div i)
#
# Note that the large numbers that we deal with can
# overflow 64-bit integers.

proc ts(n, gcd: int): int =
  if n == 0:
    result = 0
  elif n == 1 and gcd == 1:
    result = 1
  elif gcd == 1:
    result = n*(n+1) div 2
    for i in 2..n:
      result -= ts(n, i)
  else:
    result = ts(n div gcd, 1)

# Below is the optimized version of the same algorithm.

proc ts(n: int): int =
  if n == 0:
    result = 0
  elif n == 1:
    result = 1
  else:
    if n <= max and ts_mem[n] > 0:
      return ts_mem[n]
    result = n*(n+1) div 2
    var p = n
    var k = 2
    while k < n div k:
      let pold = p
      p = n div k
      k += 1
      let t = ts(n div pold)
      result -= t * (pold-p)
    while p >= 2:
      result -= ts(n div p)
      p -= 1
    if n <= max:
      ts_mem[n] = result

proc ts(n: int128): int128 =
  if n <= 2_000_000_000:
    result = ts(n.toInt)
  else:
    result = n*(n+1) div 2
    var p = n
    var k = 2
    while k < n div k:
      let pold = p
      p = n div k
      k += 1
      let t = ts(n div pold)
      result = result - t * (pold-p)
    while p >= 2:
      result = result - ts(n div p)
      p = p - 1

echo ts(42_000_000_000.toInt128)

Thưa quý vị, đây là những gì tôi gọi là phù thủy.
Anna Jokela

2
Cách tiếp cận tuyệt vời để tính tổng trực tiếp, nhưng thật không may, nó không tính hàm tổng cho nhiều số nhất có thể , đó là thách thức được đưa ra ở trên. Mã của bạn thực sự tính toán kết quả (thậm chí không phải là kết quả của hàm tổng) chỉ cho vài nghìn số (xấp xỉ 2*sqrt(n)), điều này làm cho điểm thấp hơn nhiều.
Howard

7

C #: 49.000 (980.000.000 / 20.000)

/codegolf//a/26800 "Mã của Howard".
Nhưng sửa đổi, giá trị phi được tính cho số nguyên lẻ.

using System;
using sw = System.Diagnostics.Stopwatch;
class Program
{
    static void Main()
    {
        sw sw = sw.StartNew();
        Console.Write(sumPhi(980000000) + " " + sw.Elapsed);
        sw.Stop(); Console.Read();
    }

    static long sumPhi(int n)  // sum phi[i] , 1 <= i <= n
    {
        long s = 0; int[] phi;
        if (n < 1) return 0; phi = buildPhi(n + 1);
        for (int i = 1; i <= n; i++) s += getPhi(i, phi);
        return s;
    }

    static int getPhi(int i, int[] phi)
    {
        if ((i & 1) > 0) return phi[i >> 1];
        if ((i & 3) > 0) return phi[i >> 2];
        int z = ntz(i); return phi[i >> z >> 1] << z - 1;
    }

    static int[] buildPhi(int n)  // phi[i >> 1] , i odd , i < n
    {
        int i, j, y, x, q, r, f; int[] phi;
        if (n < 2) return new int[] { 0 };
        phi = new int[n / 2]; phi[0] = 1;
        for (j = 2, i = 3; i < n; i *= 3, j *= 3) phi[i >> 1] = j;
        for (x = 4, i = 5; i <= n >> 1; i += x ^= 6)
        {
            if (phi[i >> 1] > 0) continue; phi[i >> 1] = i ^ 1;
            for (j = 3, y = 3 * i; y < n; y += i << 1, j += 2)
            {
                if (phi[j >> 1] == 0) continue; q = j; f = i ^ 1;
                while ((r = q) == i * (q /= i)) f *= i;
                phi[y >> 1] = f * phi[r >> 1];
            }
        }
        for (; i < n; i += x ^= 6)  // primes > n / 2 
            if (phi[i >> 1] == 0)
                phi[i >> 1] = i ^ 1;
        return phi;
    }

    static int ntz(int i)  // number of trailing zeros
    {
        int z = 1;
        if ((i & 0xffff) == 0) { z += 16; i >>= 16; }
        if ((i & 0x00ff) == 0) { z += 08; i >>= 08; }
        if ((i & 0x000f) == 0) { z += 04; i >>= 04; }
        if ((i & 0x0003) == 0) { z += 02; i >>= 02; }
        return z - (i & 1);
    }
}

Điểm mới: 61.000 (1.220.000.000 / 20.000)
Trong "App.config" tôi đã phải thêm "gc ALLowVeryLargeObjects enable = true".

    static long sumPhi(int n)
    {
        int i1, i2, i3, i4, z; long s1, s2, s3, s4; int[] phi;
        if (n < 1) return 0; phi = buildPhi(n + 1); n -= 4; z = 2;
        i1 = 1; i2 = 2; i3 = 3; i4 = 4; s1 = s2 = s3 = s4 = 0;
        if (n > 0)
            for (; ; )
            {
                s1 += phi[i1 >> 1];
                s2 += phi[i2 >> 2];
                s3 += phi[i3 >> 1];
                s4 += phi[i4 >> z >> 1] << z - 1;
                i1 += 4; i2 += 4; i3 += 4; i4 += 4;
                n -= 4; if (n < 0) break;
                if (z == 2)
                {
                    z = 3; i4 >>= 3;
                    while ((i4 & 3) == 0) { i4 >>= 2; z += 2; }
                    z += i4 & 1 ^ 1;
                    i4 = i3 + 1;
                }
                else z = 2;
            }
        if (n > -4) s1 += phi[i1 >> 1];
        if (n > -3) s2 += phi[i2 >> 2];
        if (n > -2) s3 += phi[i3 >> 1];
        if (n > -1) s4 += phi[i4 >> z >> 1] << z - 1;
        return s1 + s2 + s3 + s4;
    }

    static int[] buildPhi(int n)
    {
        int i, j, y, x, q0, q1, f; int[] phi;
        if (n < 2) return new int[] { 0 };
        phi = new int[n / 2]; phi[0] = 1;
        for (uint u = 2, v = 3; v < n; v *= 3, u *= 3) phi[v >> 1] = (int)u;
        for (x = 4, i = 5; i <= n >> 1; i += x ^= 6)
        {
            if (phi[i >> 1] > 0) continue; phi[i >> 1] = i ^ 1;
            for (j = 3, y = 3 * i; y < n; y += i << 1, j += 2)
            {
                if (phi[j >> 1] == 0) continue; q0 = j; f = i ^ 1;
                while ((q1 = q0) == i * (q0 /= i)) f *= i;
                phi[y >> 1] = f * phi[q1 >> 1];
            }
        }
        for (; i < n; i += x ^= 6)
            if (phi[i >> 1] == 0)
                phi[i >> 1] = i ^ 1;
        return phi;
    }

4

Python 3: ~ 24000 (335.000.000 / 14.000)

Phiên bản của tôi là một cổng Python của thuật toán của Howard . Chức năng ban đầu của tôi là sửa đổi thuật toán được giới thiệu trong blogpost này .

Tôi đang sử dụng các mô-đun Numpy và Numba để tăng tốc thời gian thực hiện. Lưu ý rằng thông thường bạn không cần phải khai báo các loại biến cục bộ (khi sử dụng Numba), nhưng trong trường hợp này tôi muốn nén thời gian thực hiện càng nhiều càng tốt.

Chỉnh sửa: kết hợp các hàm cấu trúc và hàm tóm tắt thành một hàm duy nhất.

C ++: 9,99s (n = 14.000); Python 3: 9,94 (n = 335.000.000)

import numba as nb
import numpy as np
import time

n = 335000000

@nb.njit("i8(i4[:])", locals=dict(
    n=nb.int32, s=nb.int64, i=nb.int32,
    j=nb.int32, q=nb.int32, f=nb.int32))

def summarum(phi):
    s = 0

    phi[1] = 1

    i = 2
    while i < n:
        if phi[i] == 0:
            phi[i] = i - 1

            j = 2

            while j * i < n:
                if phi[j] != 0:
                    q = j
                    f = i - 1

                    while q % i == 0:
                        f *= i
                        q //= i

                    phi[i * j] = f * phi[q]
                j += 1
        s += phi[i]
        i += 1
    return s

if __name__ == "__main__":
    s1 = time.time()
    a = summarum(np.zeros(n, np.int32))
    s2 = time.time()

    print(a)
    print("{}s".format(s2 - s1))

1
Bạn nên cung cấp tín dụng thích hợp khi bạn sao chép mã từ những người dùng khác.
Howard

Cập nhật với các khoản tín dụng thích hợp!
Anna Jokela

3

Đây là cách triển khai Python của tôi mà dường như có thể tạo ra ~ 60000 số trong 10 giây. Tôi đang tính hệ số bằng cách sử dụng thuật toán rho pollard và sử dụng thử nghiệm tính nguyên thủy của máy nghiền Rabin.

from Queue import Queue
import random

def gcd ( a , b ):
    while b != 0: a, b = b, a % b
    return a

def rabin_miller(p):
    if(p<2): return False
    if(p!=2 and p%2==0): return False
    s=p-1
    while(s%2==0): s>>=1
    for _ in xrange(10):
        a=random.randrange(p-1)+1
        temp=s
        mod=pow(a,temp,p)
        while(temp!=p-1 and mod!=1 and mod!=p-1):
            mod=(mod*mod)%p
            temp=temp*2
        if(mod!=p-1 and temp%2==0): return False
    return True

def pollard_rho(n):
    if(n%2==0): return 2;
    x=random.randrange(2,1000000)
    c=random.randrange(2,1000000)
    y=x
    d=1
    while(d==1):
        x=(x*x+c)%n
        y=(y*y+c)%n
        y=(y*y+c)%n
        d=gcd(x-y,n)
        if(d==n): break;
    return d;

def primeFactorization(n):
    if n <= 0: raise ValueError("Fucked up input, n <= 0")
    elif n == 1: return []
    queue = Queue()
    factors=[]
    queue.put(n)
    while(not queue.empty()):
        l=queue.get()
        if(rabin_miller(l)):
            factors.append(l)
            continue
        d=pollard_rho(l)
        if(d==l):queue.put(l)
        else:
            queue.put(d)
            queue.put(l/d)
    return factors

def phi(n):

    if rabin_miller(n): return n-1
    phi = n
    for p in set(primeFactorization(n)):
        phi -= (phi/p)
    return phi

if __name__ == '__main__':

  n = 1
  s = 0

  while n < 60000:
    n += 1
    s += phi(n)
  print(s)

2

(2 n ) = 2 n - 1
Σ (2 i ) = 2 i - 1 với i từ 1 đến n

Đầu tiên, một cái gì đó để tìm thời gian:

import os
from time import perf_counter

SEARCH_LOWER = -1
SEARCH_HIGHER = 1

def integer_binary_search(start, lower=None, upper=None, big_jump=1):
    if lower is not None and lower == upper:
        raise StopIteration # ?

    result = yield start

    if result == SEARCH_LOWER:
        if lower is None:
            yield from integer_binary_search(
                start=start - big_jump,
                lower=None,
                upper=start - 1,
                big_jump=big_jump * 2)
        else:
            yield from integer_binary_search(
                start=(lower + start) // 2,
                lower=lower,
                upper=start - 1)
    elif result == SEARCH_HIGHER:
        if upper is None:
            yield from integer_binary_search(
                start=start + big_jump,
                lower=start + 1,
                upper=None,
                big_jump=big_jump * 2)
        else:
            yield from integer_binary_search(
                start=(start + upper) // 2,
                lower=start + 1,
                upper=upper)
    else:
        raise ValueError('Expected SEARCH_LOWER or SEARCH_HIGHER.')

search = integer_binary_search(start=1000, lower=1, upper=None, big_jump=2500)
n = search.send(None)

while True:
    print('Trying with %d iterations.' % (n,))

    os.spawnlp(
        os.P_WAIT,
        'g++', 'g++', '-Wall', '-Wextra', '-pedantic', '-O0', '-o', 'reference',
        '-DITERATIONS=%d' % (n,),
        'reference.cpp')

    start = perf_counter()
    os.spawnl(os.P_WAIT, './reference', './reference')
    end = perf_counter()
    t = end - start

    if t >= 10.1:
        n = search.send(SEARCH_LOWER)
    elif t <= 9.9:
        n = search.send(SEARCH_HIGHER)
    else:
        print('%d iterations in %f seconds!' % (n, t))
        break

Đối với mã tham chiếu, đối với tôi, đó là:

...
Đang cố gắng với 14.593 lần lặp lại.
64724364
14593 lần lặp trong 9,987747 giây!

Bây giờ, Haskell:

import System.Environment (getArgs)

phiSum :: Integer -> Integer
phiSum n = 2 ^ n - 1

main :: IO ()
main = getArgs >>= print . phiSum . (2^) . read . head

Nó tạo ra một cái gì đó với 2525224 chữ số trong 0,718 giây. Và bây giờ tôi chỉ nhận thấy bình luận của @ Howard.


Bạn có thể gửi một số điểm với tổng số liên tiếp bắt đầu từ 1 bạn quản lý để tổng hợp?
qwr

@qwr, đó sẽ là 0. Nếu bạn muốn các số liên tiếp, bạn nên chỉ định nó trong câu hỏi của mình =)
Ry-

Tôi đã làm. Tôi đã chỉnh sửa nó rồi, tôi sẽ chỉnh sửa lại.
qwr

2

Matlab: 1464 = 26355867/18000

Tôi không thể kiểm tra mã của bạn để tôi chia cho 18000 vì nó đại diện cho máy tính nhanh nhất trong số những người đã thử nghiệm. Tôi đã đến điểm số bằng cách sử dụng tài sản này:

  • nếu p là số nguyên tố, phi (p) = p - 1 (với p <10 ^ 20)

Tôi thích nhất đó là một lót:

sum(primes(500000000)-1)

1
Còn phi(p)đối với tất cả những người không phải là thủ tướng pthì sao?
Geobits

2
@Geobits Tôi đã bỏ qua những câu hỏi đó vì câu hỏi không đề cập đến những con số bạn nên sử dụng, miễn là chúng thực sự được tính toán.
Dennis Jaheruddin

Ah, đã không nhận thấy rằng trong từ ngữ. Tốt đẹp.
Geobits

Bạn thậm chí không đăng một số điểm ...
qwr

1
... Làm thế nào có thể không có Matlab & C ++ trên cùng một máy tính?
Kyle Kanos

1

Con trăn 2.7: 10.999 (165975/15090)

Pypy 2.3.1: 28.496 (430000/15090)

Một số phương pháp thú vị tôi sử dụng:

Thử nghiệm giả mã mạnh Rabin-Miller - Một thử nghiệm nguyên thủy cung cấp thuật toán xác suất hiệu quả để xác định xem một số đã cho có phải là số nguyên tố không

Công thức sản phẩm của Euler - Sản phẩm vượt quá các số nguyên tố riêng biệt chia n

Công thức sản phẩm của Euber

Mã số:

import math
import random

#perform a Modular exponentiation
def modular_pow(base, exponent, modulus):
    result=1
    while exponent>0:
        if exponent%2==1:
           result=(result * base)%modulus
        exponent=exponent>>1
        base=(base * base)%modulus
    return result

#Miller-Rabin primality test
def checkMillerRabin(n,k):
    if n==2: return True
    if n==1 or n%2==0: return False

    #find s and d, with d odd
    s=0
    d=n-1
    while(d%2==0):
        d/=2
        s+=1
    assert (2**s*d==n-1)

    #witness loop
    composite=1
    for i in xrange(k):
        a=random.randint(2,n-1)
        x=modular_pow(a,d,n)
        if x==1 or x==n-1: continue
        for j in xrange(s-1):
            composite=1
            x=modular_pow(x,2,n)
            if x==1: return False #is composite
            if x==n-1: 
                composite=0
                break
        if composite==1:
            return False        #is composite
    return True                 #is probably prime

def findPrimes(n):              #generate a list of primes, using the sieve of eratosthenes

    primes=(n+2)*[True]

    for i in range(2,int(math.sqrt(n))+1):
        if primes[i]==True:
            for j in range(i**2,n+1,i):
                primes[j]=False

    primes=[i for i in range(2,len(primes)-1) if primes[i]==True]
    return primes

def primeFactorization(n,primes):   #find the factors of a number

    factors=[]

    i=0
    while(n!=1):
        if(n%primes[i]==0):
            factors.append(primes[i])
            n/=primes[i]
        else:
            i+=1

    return factors

def phi(n,primes):
    #some useful properties
    if (checkMillerRabin(n,10)==True):      #fast prime check
        return n-1

    factors=primeFactorization(n,primes)    #prime factors
    distinctive_prime_factors=set(factors)  

    totient=n
    for f in distinctive_prime_factors:     #phi = n * sum (1 - 1/p), p is a distinctive prime factor
        totient*=(1-1.0/f);

    return totient

if __name__ == '__main__':


    s=0
    N=165975
    # N=430000
    primes=findPrimes(N)    #upper bound for the number of primes
    for i in xrange(1,N):
        s+=phi(i,primes)

    print "Sum =",s 

Cảm ơn fro các thuật toán! Đó là người duy nhất tôi có thể hiểu một cách dễ dàng và không phải là người kiểm tra vũ lực khi đếm các số nguyên tố.
người dùng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.