নিমরোড: ~ 38,667 (580,000,000 / 15,000)
এই উত্তরটি বেশ সহজ পদ্ধতির ব্যবহার করে। কোডটি একটি সাধারণ মৌলিক সংখ্যা চালনী নিযুক্ত করে যা সংমিশ্রিত সংখ্যার জন্য প্রতিটি স্লটে ক্ষুদ্রতম প্রধান শক্তিগুলির মৌলিক সঞ্চয় করে (প্রাইমগুলির জন্য শূন্য), তারপরে একই পরিসরের উপরে মোট কর্ম সঞ্চালনের জন্য গতিশীল প্রোগ্রামিং ব্যবহার করে, তারপরে ফলাফলগুলি যোগ করে। প্রোগ্রামটি চালুনিটি তৈরির জন্য কার্যত তার সমস্ত সময় ব্যয় করে, তারপরে সময়ের একটি ভগ্নাংশের মোট কার্যফল গণনা করে। দেখে মনে হচ্ছে এটি একটি দক্ষ চালনী তৈরির জন্য নেমে এসেছে (সামান্য মোচড় দিয়ে যে ফলাফলটি সংশ্লেষ সংখ্যার জন্য একটি মৌলিক গুণককে বের করতে সক্ষম হতে হবে এবং মেমরির ব্যবহারকে যুক্তিসঙ্গত স্তরে রাখতে হবে)।
আপডেট: মেমরি পদচিহ্ন হ্রাস এবং ক্যাশে আচরণ উন্নত করে কর্মক্ষমতা উন্নত। 5% -10% বেশি পারফরম্যান্স আটকানো সম্ভব, তবে কোড জটিলতা বৃদ্ধি লাভজনক নয়। শেষ পর্যন্ত, এই অ্যালগরিদমটি মূলত একটি সিপিইউ'র ভন নিউমান বোতল ব্যায়াম অনুশীলন করে এবং খুব কম অ্যালগরিদমিক টুইট রয়েছে যা এটির কাছাকাছি আসতে পারে।
সি ++ কোডটি সমস্ত অপ্টিমাইজেশনের সাথে সংকলিত হওয়ার উদ্দেশ্যে নয় এবং অন্য কেউ তা করেনি বলে পারফরম্যান্স ডিভায়ারটিকেও আপডেট করেছে। :)
আপডেট 2: উন্নত মেমরি অ্যাক্সেসের জন্য অনুকূলিতকরণ চালনা অপারেশন। বড় আকারের প্রাইমগুলি (~ 10% স্পিডআপ) সিভ করার সময় এখন মেমকিপি () (~ 5% স্পিডআপ) এর মাধ্যমে বাল্কে ছোট ছোট প্রাইমগুলি পরিচালনা করা এবং 2, 3 এবং 5 এর বহুগুণ এড়িয়ে যাওয়া।
সি ++ কোড: ৯.৯ সেকেন্ড (জি ++ ৪.৯ সহ)
নিম্রড কোড: 9.9 সেকেন্ড (-ড: রিলিজ, জিসিসি 4.9 ব্যাকএন্ড সহ)
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)