Md Golam Rahman Tushar

Blog 2015

Find the sum of divisors from 1 to n

An optimized O(√n) way to find the sum of divisors of the first n natural numbers.

ধরা যাক, আপনাকে একটা সংখ্যা n দিয়ে বললো 1 থেকে n পর্যন্ত সংখ্যাগুলোর divisor(1 এবং সেই সংখ্যা বাদে) গুলোর যোগফল বের করতে।

যেমনঃ 6 এর divisor গুলো হচ্ছে 2, 3। যোগফল হচ্ছে 5।

এখন n এর মান যদি 6 হয় তাহলে উত্তর হবে 0+0+0+2+0+5 = 7। যেহেতু 1, 2, 3, 4, 5 ,6 সংখ্যাগুলোর divisor গুলোর যোগফল যথাক্রমে 0, 0, 0, 2, 0, 5।

O(n) solution

এই প্রবলেমটার সবচেয়ে সহজ সমাধান হচ্ছে 1 থেকে n পর্যন্ত একটা for লুপ চালিয়ে প্রত্যেকটি i এর জন্য (floor(n / i) – 1) * i বের করে যোগ করা। এইখানে floor(n/i) এর মাধ্যমে বের করা হচ্ছে 1 থেকে n পর্যন্ত কতগুলো সংখ্যা i দিয়ে divisible.

যেমনঃ 6/2 = 3, এর মানে হচ্ছে 1 থেকে 6 পর্যন্ত 3 টি সংখ্যা (2, 4, 6) 2 দিয়ে divisible.

আর floor(n/i) থেকে 1 বিয়োগ করা হচ্ছে কারণ divisor হিসেবে নিজেকে নেয়া যাবে না। অর্থাৎ এখানে 6 এর divisor হচ্ছে শুধু 2 এবং 3।

O(n/2) solution

উপরের সলুশনের ক্ষেত্রে আসলে n/2 পর্যন্ত ফর লুপ চালালেই আমরা সলুশন পেয়ে যাব কারণ n/2+1 থেকে n পর্যন্ত সংখ্যা গুলো নিজেদের ছাড়া 1 থেকে n পর্যন্ত অন্য কোন সংখ্যার-ই divisor না।

O(sqrt(n)) solution

আমরা আগেই দেখেছি, যদি floor(n/i) = x হয় এর মানে হচ্ছে 1 থেকে n পর্যন্ত নিজেকে ছাড়া x-1 টি সংখ্যা i দ্বারা divisible. উল্টাটাও কিন্তু সত্য, মানে হচ্ছে 1 থেকে n পর্যন্ত নিজেকে ছাড়া i-1 টি সংখ্যা x দ্বারা divisible.

ধরা যাক, n = 30। 1 থেকে 30 পর্যন্তু সংখ্যাগুলোর divisor (1 এবং নিজেকে বাদে) গুলো নিচে দেয়া হলঃ

 1 –
 2 –
 3 –
 4 – 2
 5 –
 6 – 2, 3
 7 –
 8 – 2, 4
 9 – 3
10 – 2, 5
11 –
12 – 2, 3, 4, 6
13 –
14 – 2, 7
15 – 3, 5
16 – 2, 4, 8
17 –
18 – 2, 3, 6, 9
19 –
20 – 2, 4, 5, 10
21 – 3, 7
22 – 2, 11
23 –
24 – 2, 4, 6, 12
25 – 5
26 – 2, 13
27 – 3, 9
28 – 2, 4, 7, 14
29 –
30 – 2, 3, 5, 6, 10, 15

floor(30/2) = 15, অর্থাৎ 1 থেকে 30 পর্যন্ত 2 টি সংখ্যা 15 দ্বারা divisible, নিজেকে বাদ দিলে 1 শুধু একটি সংখ্যা(20) 15 দ্বারা divisible।

আবার floor(30/3) = 10, অর্থাৎ 1 থেকে 30 পর্যন্ত নিজেকে বাদে 2 টি সংখ্যা (20, 30) 10 দ্বারা divisible।

এখন একটূ খেয়াল করলে দেখা যাবে যে, floor(30/3)+1 = 11 থেকে floor(30/2) = 15 পর্যন্ত 5 টি সংখ্যার (11, 12, 13, 14, 15) প্রত্যেকটি 1 থেকে 30 পর্যন্ত 2 টি সংখ্যার divisible।

একইভাবে floor(30/4)+1 = 8 থেকে floor(30/3) = 10 পর্যন্ত 3 টি সংখ্যার (8, 9, 10) প্রত্যেকটি 1 থেকে 30 পর্যন্ত 3 টি সংখ্যার divisible।

অর্থাৎ, floor(n/i) + 1 থেকে floor(n/(i+1)) পর্যন্ত সংখ্যাগুলোর প্রত্যেকটি 1 থেকে n পর্যন্ত i টি সংখ্যার divisible।

তাহলে, আমরা আসলে 1 থেকে sqrt(n) পর্যন্ত ফর লুপ চালালেই সলুশন পেয়ে যাচ্ছি।

Code

for(i=2; i <= sqrt(n); i++) {
    ans += ((n/i) - 1) * i;

    temp = n / i;
    if(temp > i) {
        a = n / (i+1);
        b = n / i;
        sum1 = (a * (a+1)) / 2;
        sum2 = (b * (b+1)) / 2;

        ans += (sum2 - sum1) * (i - 1);
    }
}

এই ব্লগটা খুবই তাড়াহুড়ো করে লিখা, তাই ঠিকমত সবকিছু গুছায়ে বলা হয় নাই। তাছাড়া এইটাই আমার ফার্স্ট ব্লগ, তাই পড়ে কিছু না বুজলে আমার কিছু করার নাই :p । আর যদি বুজতে পারলে আলোর (lightoj.com) 1098 নাম্বার প্রবলেমটা সল্ভ করা যেতে পারে, কোড তো দিয়াই দিলাম :p ।

তবে আশা করি, সামনে আরো সুন্দর করে সময় নিয়ে নিয়মিত ব্লগ লিখব :D