有效计算范围内整数的除数总数

发布于 2025-01-03 05:36:30 字数 881 浏览 1 评论 0原文

给定范围 [1, 2 百万],对于这个范围内的每个数字,我需要生成 并将每个整数的约数个数存储在数组中。

因此,如果 x=p1^(a1)*p2^a2*p3^a3,其中 p1、p2、p3 是素数, x 的约数总数由 (p1+1)(p2+1)(p3+1) 给出。我生成了所有 2000 以下的素数,对于该范围内的每个整数,我进行了试除法 得到每个质因数的幂,然后用上面的公式计算 除数的数量并存储在数组中。 但是,这样做非常慢,大约需要 5 秒才能生成除数的数量 对于给定范围内的所有数字。

我们可以用其他有效的方式求和吗?可能不需要分解每个 数字?

下面是我现在使用的代码。

typedef unsigned long long ull;
void countDivisors(){
    ull PF_idx=0, PF=0, ans=1, N=0, power;
    for(ull i=2; i<MAX; ++i){
        if (i<SIEVE_SIZE and isPrime[i]) factors[i]=2;
        else{
        PF_idx=0;
        PF=primes[PF_idx];
        ans=1;
        N=i;
        while(N!=1 and (PF*PF<=N)){
            power = 0;
            while(N%PF==0){ N/=PF; ++power;}
            ans*=(power+1);
            PF = primes[++PF_idx];
        }
        if (N!=1) ans*=2;
        factors[i] = ans;
        }
    }
}

Given the range [1, 2 Million], for each number in this range I need to generate
and store the number of the divisors of each integer in an array.

So if x=p1^(a1)*p2^a2*p3^a3, where p1, p2, p3 are primes,
the total number of divisors of x is given by (p1+1)(p2+1)(p3+1). I generated all
the primes below 2000 and for each integer in the range, I did trial division
to get the power of each prime factor and then used the formula above to calculate
the number of divisors and stored in an array.
But, doing this is quite slow and takes around 5 seconds to generate the number of divsors
for all the numbers in the given range.

Can we do this sum in some other efficient way, may be without factorizing each
of the numbers?

Below is the code that I use now.

typedef unsigned long long ull;
void countDivisors(){
    ull PF_idx=0, PF=0, ans=1, N=0, power;
    for(ull i=2; i<MAX; ++i){
        if (i<SIEVE_SIZE and isPrime[i]) factors[i]=2;
        else{
        PF_idx=0;
        PF=primes[PF_idx];
        ans=1;
        N=i;
        while(N!=1 and (PF*PF<=N)){
            power = 0;
            while(N%PF==0){ N/=PF; ++power;}
            ans*=(power+1);
            PF = primes[++PF_idx];
        }
        if (N!=1) ans*=2;
        factors[i] = ans;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云淡风轻 2025-01-10 05:36:30

首先你的公式是错误的。根据你的公式,12的约数之和应该是12。实际上是28。正确的公式是 (p1a1 - 1)*(p2a2 - 1) * ... * (pkak - 1)/( (p1 - 1) * (p 2 - 1) * ... * (pk - 1) )

也就是说,最简单的方法可能就是进行筛子。人们可以巧妙地利用偏移量,但为了简单起见,只需创建一个包含 2,000,001 个整数(从 0 到 200 万)的数组。将其初始化为 0。然后:

for (ull i = 1; i < MAX; ++i) {
    for (ull j = i; j < MAX; j += i) {
        factors[j] += i;
    }
}

这可能感觉效率低下,但也没有那么糟糕。 N 之前的数字所需的总功为 N + N/2 + N/3 + ... + N/N = O(N log(N)) 这比试除法要小几个数量级。而且运算都是加法和比较,对于整数来说速度很快。

如果您想继续使用原来的想法和公式,您可以使用改进的埃拉托斯特尼筛创建一个 1 到 200 万的数组,列出每个数字的素因数,从而提高效率。构建该数组相当快,您可以获取任何数字并对其进行因式分解,这比使用试除法要快得多。

First of all your formula is wrong. According to your formula, the sum of the divisors of 12 should be 12. In fact it is 28. The correct formula is (p1a1 - 1)*(p2a2 - 1) * ... * (pkak - 1)/( (p1 - 1) * (p2 - 1) * ... * (pk - 1) ).

That said, the easiest approach is probably just to do a sieve. One can get clever with offsets, but for simplicity just make an array of 2,000,001 integers, from 0 to 2 million. Initialize it to 0s. Then:

for (ull i = 1; i < MAX; ++i) {
    for (ull j = i; j < MAX; j += i) {
        factors[j] += i;
    }
}

This may feel inefficient, but it is not that bad. The total work taken for the numbers up to N is N + N/2 + N/3 + ... + N/N = O(N log(N)) which is orders of magnitude less than trial division. And the operations are all addition and comparison, which are fast for integers.

If you want to proceed with your original idea and formula, you can make that more efficient by using a modified sieve of Eratosthenes to create an array from 1 to 2 million listing a prime factor of each number. Building that array is fairly fast, and you can take any number and factorize it much, much more quickly than you could with trial division.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文