Skip to content

Update divisors.md #1127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 27, 2023
Merged

Update divisors.md #1127

merged 3 commits into from
Aug 27, 2023

Conversation

md-shamim-ahmad
Copy link
Contributor

Hey,
Since pull request #1079 has not completed and is not working properly
that's why I have added simple code for number of divisors and sum of divisors

@github-actions
Copy link
Contributor

Visit the preview URL for this PR (for commit 133f1e8):

https://cp-algorithms--preview-1127-aurju4l1.web.app

(expires 2023-07-29T01:54:22.063689633Z)

Copy link
Member

@jakobkogler jakobkogler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hallo.

Thanks for the contribution. (and sorry for the long wait)

While the implementation works, I'm not particularly happy about it.
What I don't like:

  • The input parameter num is a long long, which kinda suggests that this function works also for numbers that are bigger than ints.
    However, this function needs to know all prime numbers until the num, which you probably don't have for such big numbers.
  • And also this method presented here is kinda slow, as it also needs to visit all primes that exist up to num. E.g. if num ~= 10^9, than there are ~50 000 000 prime numbers that you visit every time.

A better implementation would be something like the following. It actually doesn't require a list of prime numbers, and also requires a lot less modulo tests. E.g. for num ~= 10^9 your code does ~50 000 000 modulo operations, while the following code only does $\sqrt{10^9} ~= 34 000$ many as it uses the typical trick of factorizing the prime number by going up to the root of the number (https://cp-algorithms.com/algebra/factorization.html#trial-division). It also works reasonable fast for larger numbers.
(and it could even be improved, if you skip the even numbers).

long long numberOfDivisors(long long num) {
    long long total = 1;
    for (int i = 2; (long long)i * i <= num; i++) {
        if (num % i == 0) {
            int e = 0;
            do {
                e++;
                num /= i;
            } while (num % i == 0);
            total *= e + 1;
        }
    }
    // handle the last prime
    if (num > 1) {
        total *= 2;
    }
    return total;
}

As comparison, your code runs in $O(n / \log{n})$ (as there are that many primes up to $n$), and my code runs in $O(\sqrt{n})$.

Alternatively, you could even do it a lot faster, if you precompute a lot of stuff.
If you precompute the largest prime factor of every number, you can compute the the number of divisors in $O(\log{n})$ time. See https://github.com/jakobkogler/Algorithm-DataStructures/blob/master/Math/Divisors.h
This thou has the disadvantage, that it requires a lot of memory. So it also doesn't work for large numbers.

Would you be interested in adding that code (the $O(\sqrt{n})$ one) and also adapting it to the sum of divisors?

Btw, for the sum of divisors you don't need to use the pow function, you can instead just multiple by p in the loop instead of incrementing the counter.

@github-actions
Copy link
Contributor

Visit the preview URL for this PR (for commit 6f79dcb):

https://cp-algorithms--preview-1127-wbaaeay8.web.app

(expires 2023-08-31T08:10:52.231341480Z)

@md-shamim-ahmad
Copy link
Contributor Author

md-shamim-ahmad commented Aug 24, 2023

thanks for your replay,
By comparison time complexity, your code is faster than mine.
Can we use below code to make it more easier?

long long numberOfDivisors(long long num) {
    long long total = 0;
    for (int i = 2; (long long)i * i <= num; i++) {
        if (num % i == 0) {
            if (num / i == i)
                total++;
            else
                total += 2;
        }
    }
    return total;
}

Time complexity of this code is also O($\sqrt{n}$) but this code is easier than the previous code.

And Sum of Divisors code will be as,

long long SumOfDivisors(long long num) {
    long long total = 1;

    for (int i = 2; (long long)i * i <= num; i++) {
        if (num % i == 0) {
            int e = 0;
            do {
                e++;
                num /= i;
            } while (num % i == 0);

            long long sum = 0, pow = 1;
            do {
                sum += pow;
                pow *= i;
            } while (e-- > 0);
            total *= sum;
        }
    }
    if (num > 1) {
        total *= (1 + num);
    }
    return total;
}

@github-actions
Copy link
Contributor

Visit the preview URL for this PR (for commit f774c39):

https://cp-algorithms--preview-1127-wbaaeay8.web.app

(expires 2023-08-31T14:19:36.557950582Z)

Copy link
Member

@jakobkogler jakobkogler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. Thanks.

@jakobkogler
Copy link
Member

@md-shamim-ahmad Yeah, you are correct.
Just doing a normal loop up to the square root has the same complexity than doing a prime factorization with the same loop.
Funny, that I didn't realize that when I wrote the article.

The two methods that I introduced in the article work fast, if you already know the prime factorization (or compute the prime factorization with a faster method). But it doesn't give any immediate benefits over the simpler method.

If you are up for it, you could make a 2nd pull-request and add the shorter code at the beginning of the article. With some short explanation, e.g. something like "the simple way of computing the divisors is by iterating up to the square root and ...: <SHORT_CODE> If you however know the prime factorization of the number, then you can speed the computation up by using math..."

@jakobkogler jakobkogler merged commit 15ff2e9 into cp-algorithms:master Aug 27, 2023
@jakobkogler jakobkogler mentioned this pull request Aug 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy