计算给定数字的约数的算法

发布于 2024-07-05 23:42:53 字数 190 浏览 11 评论 0原文

计算给定数字的除数数量的最佳算法(性能方面)是什么?

如果您可以提供伪代码或某些示例的链接,那就太好了。

编辑:所有的答案都非常有帮助,谢谢。 我正在实施阿特金筛法,然后我将使用类似于乔纳森·莱夫勒(Jonathan Leffler)指出的东西。 Justin Bozonier 发布的链接提供了有关我想要的更多信息。

What would be the most optimal algorithm (performance-wise) to calculate the number of divisors of a given number?

It'll be great if you could provide pseudocode or a link to some example.

EDIT: All the answers have been very helpful, thank you. I'm implementing the Sieve of Atkin and then I'm going to use something similar to what Jonathan Leffler indicated. The link posted by Justin Bozonier has further information on what I wanted.

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

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

发布评论

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

评论(26

十二 2024-07-12 23:43:15

我不知道最有效的方法,但我会执行以下操作:

  • 创建一个素数表来查找小于或等于数字平方根的所有素数(就我个人而言,我会使用阿特金筛法)
  • 计算所有小于或等于该数字的平方根的素数,并将其乘以二。 如果数字的平方根是整数,则从计数变量中减一。

应该可以工作 \o/

如果您需要,我明天可以用 C 编写一些代码来演示。

I don't know the MOST efficient method, but I'd do the following:

  • Create a table of primes to find all primes less than or equal to the square root of the number (Personally, I'd use the Sieve of Atkin)
  • Count all primes less than or equal to the square root of the number and multiply that by two. If the square root of the number is an integer, then subtract one from the count variable.

Should work \o/

If you need, I can code something up tomorrow in C to demonstrate.

百思不得你姐 2024-07-12 23:43:14

我想这个会很方便而且精确

script.pyton

>>>factors=[ x for x in range (1,n+1) if n%x==0]
打印 len(因子)

i guess this one will be handy as well as precise

script.pyton

>>>factors=[ x for x in range (1,n+1) if n%x==0]
print len(factors)

单挑你×的.吻 2024-07-12 23:43:14

尝试按照以下思路进行操作:

int divisors(int myNum) {
    int limit = myNum;
    int divisorCount = 0;
    if (x == 1) 
        return 1;
    for (int i = 1; i < limit; ++i) {
        if (myNum % i == 0) {
            limit = myNum / i;
            if (limit != i)
                divisorCount++;
            divisorCount++;
        }
    }
    return divisorCount;
}

Try something along these lines:

int divisors(int myNum) {
    int limit = myNum;
    int divisorCount = 0;
    if (x == 1) 
        return 1;
    for (int i = 1; i < limit; ++i) {
        if (myNum % i == 0) {
            limit = myNum / i;
            if (limit != i)
                divisorCount++;
            divisorCount++;
        }
    }
    return divisorCount;
}
|煩躁 2024-07-12 23:43:13

我想这就是您正在寻找的。我正是按照您的要求做的。
复制并粘贴到记事本中。另存为 *.bat.Run。输入数字。将过程乘以 2,这就是除数。我是故意这样做的,这样可以更快地确定除数:

请注意,CMD 变量不能支持值超过 999999999

@echo off

modecon:cols=100 lines=100

:start
title Enter the Number to Determine 
cls
echo Determine a number as a product of 2 numbers
echo.
echo Ex1 : C = A * B
echo Ex2 : 8 = 4 * 2
echo.
echo Max Number length is 9
echo.
echo If there is only 1 proces done  it
echo means the number is a prime number
echo.
echo Prime numbers take time to determine
echo Number not prime are determined fast
echo.

set /p number=Enter Number : 
if %number% GTR 999999999 goto start

echo.
set proces=0
set mindet=0
set procent=0
set B=%Number%

:Determining

set /a mindet=%mindet%+1

if %mindet% GTR %B% goto Results

set /a solution=%number% %%% %mindet%

if %solution% NEQ 0 goto Determining
if %solution% EQU 0 set /a proces=%proces%+1

set /a B=%number% / %mindet%

set /a procent=%mindet%*100/%B%

if %procent% EQU 100 set procent=%procent:~0,3%
if %procent% LSS 100 set procent=%procent:~0,2%
if %procent% LSS 10 set procent=%procent:~0,1%

title Progress : %procent% %%%



if %solution% EQU 0 echo %proces%. %mindet% * %B% = %number%
goto Determining

:Results

title %proces% Results Found
echo.
@pause
goto start

I think this is what you are looking for.I does exactly what you asked for.
Copy and Paste it in Notepad.Save as *.bat.Run.Enter Number.Multiply the process by 2 and thats the number of divisors.I made that on purpose so the it determine the divisors faster:

Pls note that a CMD varriable cant support values over 999999999

@echo off

modecon:cols=100 lines=100

:start
title Enter the Number to Determine 
cls
echo Determine a number as a product of 2 numbers
echo.
echo Ex1 : C = A * B
echo Ex2 : 8 = 4 * 2
echo.
echo Max Number length is 9
echo.
echo If there is only 1 proces done  it
echo means the number is a prime number
echo.
echo Prime numbers take time to determine
echo Number not prime are determined fast
echo.

set /p number=Enter Number : 
if %number% GTR 999999999 goto start

echo.
set proces=0
set mindet=0
set procent=0
set B=%Number%

:Determining

set /a mindet=%mindet%+1

if %mindet% GTR %B% goto Results

set /a solution=%number% %%% %mindet%

if %solution% NEQ 0 goto Determining
if %solution% EQU 0 set /a proces=%proces%+1

set /a B=%number% / %mindet%

set /a procent=%mindet%*100/%B%

if %procent% EQU 100 set procent=%procent:~0,3%
if %procent% LSS 100 set procent=%procent:~0,2%
if %procent% LSS 10 set procent=%procent:~0,1%

title Progress : %procent% %%%



if %solution% EQU 0 echo %proces%. %mindet% * %B% = %number%
goto Determining

:Results

title %proces% Results Found
echo.
@pause
goto start
<逆流佳人身旁 2024-07-12 23:43:13

这不就是一个因数分解的问题——确定该数的所有因数吗? 然后,您可以决定是否需要一个或多个因素的所有组合。

因此,一种可能的算法是:

factor(N)
    divisor = first_prime
    list_of_factors = { 1 }
    while (N > 1)
        while (N % divisor == 0)
            add divisor to list_of_factors
            N /= divisor
        divisor = next_prime
    return list_of_factors

然后由您结合这些因素来确定答案的其余部分。

Isn't this just a question of factoring the number - determining all the factors of the number? You can then decide whether you need all combinations of one or more factors.

So, one possible algorithm would be:

factor(N)
    divisor = first_prime
    list_of_factors = { 1 }
    while (N > 1)
        while (N % divisor == 0)
            add divisor to list_of_factors
            N /= divisor
        divisor = next_prime
    return list_of_factors

It is then up to you to combine the factors to determine the rest of the answer.

最终幸福 2024-07-12 23:43:12

这是我写的一个函数。 最坏的时间复杂度是 O(sqrt(n)),而最好的时间复杂度是 O(log(n))。 它为您提供所有素因数及其出现次数。

public static List<Integer> divisors(n) {   
    ArrayList<Integer> aList = new ArrayList();
    int top_count = (int) Math.round(Math.sqrt(n));
    int new_n = n;

    for (int i = 2; i <= top_count; i++) {
        if (new_n == (new_n / i) * i) {
            aList.add(i);
            new_n = new_n / i;
            top_count = (int) Math.round(Math.sqrt(new_n));
            i = 1;
        }
    }
    aList.add(new_n);
    return aList;
}

Here is a function that I wrote. it's worst time complexity is O(sqrt(n)),best time on the other hand is O(log(n)). It gives you all the prime divisors along with the number of its occurence.

public static List<Integer> divisors(n) {   
    ArrayList<Integer> aList = new ArrayList();
    int top_count = (int) Math.round(Math.sqrt(n));
    int new_n = n;

    for (int i = 2; i <= top_count; i++) {
        if (new_n == (new_n / i) * i) {
            aList.add(i);
            new_n = new_n / i;
            top_count = (int) Math.round(Math.sqrt(new_n));
            i = 1;
        }
    }
    aList.add(new_n);
    return aList;
}
悟红尘 2024-07-12 23:43:12

@Kendall

我测试了你的代码并做了一些改进,现在它甚至更快了。
我还用@هك٠پپ٠的代码进行了测试,这也比他的代码更快。

long long int FindDivisors(long long int n) {
  long long int count = 0;
  long long int i, m = (long long int)sqrt(n);
  for(i = 1;i <= m;i++) {
    if(n % i == 0)
      count += 2;
  }
  if(n / m == m && n % m == 0)
    count--;
  return count;
}

@Kendall

I tested your code and made some improvements, now it is even faster.
I also tested with @هومن جاویدپور code, this is also faster than his code.

long long int FindDivisors(long long int n) {
  long long int count = 0;
  long long int i, m = (long long int)sqrt(n);
  for(i = 1;i <= m;i++) {
    if(n % i == 0)
      count += 2;
  }
  if(n / m == m && n % m == 0)
    count--;
  return count;
}
北城半夏 2024-07-12 23:43:11

下面是一个 C 程序,用于查找给定数字的约数个数。

上述算法的复杂度为O(sqrt(n))。

该算法对于完全平方数和非完全平方数都可以正确工作。

请注意,循环的上限设置为数字的平方根,以使算法最有效。

请注意,将上限存储在单独的变量中也可以节省时间,您不应在 for 循环的条件部分中调用 sqrt 函数,这也节省了计算时间。

#include<stdio.h>
#include<math.h>
int main()
{
    int i,n,limit,numberOfDivisors=1;
    printf("Enter the number : ");
    scanf("%d",&n);
    limit=(int)sqrt((double)n);
    for(i=2;i<=limit;i++)
        if(n%i==0)
        {
            if(i!=n/i)
                numberOfDivisors+=2;
            else
                numberOfDivisors++;
        }
    printf("%d\n",numberOfDivisors);
    return 0;
}

除了上面的 for 循环,您还可以使用下面的循环,它的效率更高,因为这样就不需要查找数字的平方根。

for(i=2;i*i<=n;i++)
{
    ...
}

The following is a C program to find the number of divisors of a given number.

The complexity of the above algorithm is O(sqrt(n)).

This algorithm will work correctly for the number which are perfect square as well as the numbers which are not perfect square.

Note that the upperlimit of the loop is set to the square-root of number to have the algorithm most efficient.

Note that storing the upperlimit in a separate variable also saves the time, you should not call the sqrt function in the condition section of the for loop, this also saves your computational time.

#include<stdio.h>
#include<math.h>
int main()
{
    int i,n,limit,numberOfDivisors=1;
    printf("Enter the number : ");
    scanf("%d",&n);
    limit=(int)sqrt((double)n);
    for(i=2;i<=limit;i++)
        if(n%i==0)
        {
            if(i!=n/i)
                numberOfDivisors+=2;
            else
                numberOfDivisors++;
        }
    printf("%d\n",numberOfDivisors);
    return 0;
}

Instead of the above for loop you can also use the following loop which is even more efficient as this removes the need to find the square-root of the number.

for(i=2;i*i<=n;i++)
{
    ...
}
对不⑦ 2024-07-12 23:43:11

素数法这里就很清楚了。
P[] 是小于或等于 sq = sqrt(n) 的质数列表;

for (int i = 0 ; i < size && P[i]<=sq ; i++){
          nd = 1;
          while(n%P[i]==0){
               n/=P[i];
               nd++;
               }
          count*=nd;
          if (n==1)break;
          }
      if (n!=1)count*=2;//the confusing line :D :P .

     i will lift the understanding for the reader  .
     i now look forward to a method more optimized  .

the prime number method is very clear here .
P[] is a list of prime number less than or equal the sq = sqrt(n) ;

for (int i = 0 ; i < size && P[i]<=sq ; i++){
          nd = 1;
          while(n%P[i]==0){
               n/=P[i];
               nd++;
               }
          count*=nd;
          if (n==1)break;
          }
      if (n!=1)count*=2;//the confusing line :D :P .

     i will lift the understanding for the reader  .
     i now look forward to a method more optimized  .
忘羡 2024-07-12 23:43:10

这是计算除数的最基本方法:

class PrintDivisors
{
    public static void main(String args[])
    {

    System.out.println("Enter the number");

    // Create Scanner object for taking input
    Scanner s=new Scanner(System.in);

    // Read an int
    int n=s.nextInt();

        // Loop from 1 to 'n'
        for(int i=1;i<=n;i++)
        {

            // If remainder is 0 when 'n' is divided by 'i',
            if(n%i==0)
            {
            System.out.print(i+", ");
            }
        }

    // Print [not necessary]    
    System.out.print("are divisors of "+n);

    }
}

This is the most basic way of computing the number divissors:

class PrintDivisors
{
    public static void main(String args[])
    {

    System.out.println("Enter the number");

    // Create Scanner object for taking input
    Scanner s=new Scanner(System.in);

    // Read an int
    int n=s.nextInt();

        // Loop from 1 to 'n'
        for(int i=1;i<=n;i++)
        {

            // If remainder is 0 when 'n' is divided by 'i',
            if(n%i==0)
            {
            System.out.print(i+", ");
            }
        }

    // Print [not necessary]    
    System.out.print("are divisors of "+n);

    }
}
美人骨 2024-07-12 23:43:09

数论教科书将除数计数函数称为 tau。 第一个有趣的事实是它是乘法的,即。 τ(ab) = τ(a)τ(b) ,当 a 和 b 没有公因数时。 (证明:a 和 b 的每对约数都给出 ab 的不同约数)。

现在请注意,对于 pa 素数,τ(p**k) = k+1(p 的幂)。 因此,您可以轻松地通过分解计算 τ(n)。

然而,对大数进行因式分解可能会很慢(RSA 密码学的安全性取决于难以因式分解的两个大素数的乘积)。 这表明这个优化算法

  1. 测试数字是否是素数(快速)
  2. 如果因此,返回 2
  3. 否则,对数字进行因式分解(如果有多个大质因数则速度较慢)
  4. 计算 τ (n) 因式分解

Number theory textbooks call the divisor-counting function tau. The first interesting fact is that it's multiplicative, ie. τ(ab) = τ(a)τ(b) , when a and b have no common factor. (Proof: each pair of divisors of a and b gives a distinct divisor of ab).

Now note that for p a prime, τ(p**k) = k+1 (the powers of p). Thus you can easily compute τ(n) from its factorisation.

However factorising large numbers can be slow (the security of RSA crytopraphy depends on the product of two large primes being hard to factorise). That suggests this optimised algorithm

  1. Test if the number is prime (fast)
  2. If so, return 2
  3. Otherwise, factorise the number (slow if multiple large prime factors)
  4. Compute τ(n) from the factorisation
清晨说晚安 2024-07-12 23:43:09

除数做了一些惊人的事情:它们完全相除。 如果您想检查数字 n 的除数数量,那么跨越整个范围 1...n 显然是多余的。 我还没有对此进行任何深入的研究,但我解决了 Project Euler 的问题 12三角形数。 我的大于 500 个除数测试的解决方案运行了 309504 微秒(~0.3 秒)。 我为解决方案编写了这个除数函数。

int divisors (int x) {
    int limit = x;
    int numberOfDivisors = 1;

    for (int i(0); i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            numberOfDivisors++;
        }
    }

    return numberOfDivisors * 2;
}

每个算法都有一个弱点。 我认为这对素数来说很弱。 但由于三角形数字不是印刷的,它完美地达到了它的目的。 从我的分析来看,我认为它做得很好。

节日快乐。

Divisors do something spectacular: they divide completely. If you want to check the number of divisors for a number, n, it clearly is redundant to span the whole spectrum, 1...n. I have not done any in-depth research for this but I solved Project Euler's problem 12 on Triangular Numbers. My solution for the greater then 500 divisors test ran for 309504 microseconds (~0.3s). I wrote this divisor function for the solution.

int divisors (int x) {
    int limit = x;
    int numberOfDivisors = 1;

    for (int i(0); i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            numberOfDivisors++;
        }
    }

    return numberOfDivisors * 2;
}

To every algorithm, there is a weak point. I thought this was weak against prime numbers. But since triangular numbers are not print, it served its purpose flawlessly. From my profiling, I think it did pretty well.

Happy Holidays.

狼性发作 2024-07-12 23:43:08

您需要阿特金筛,如下所述:http://en.wikipedia.org/wiki/Sieve_of_Atkin< /a>

You want the Sieve of Atkin, described here: http://en.wikipedia.org/wiki/Sieve_of_Atkin

旧时光的容颜 2024-07-12 23:43:07

这是一个有效的解决方案:

#include <iostream>
int main() {
  int num = 20; 
  int numberOfDivisors = 1;

  for (int i = 2; i <= num; i++)
  {
    int exponent = 0;
    while (num % i == 0) {
        exponent++; 
        num /= i;
    }   
    numberOfDivisors *= (exponent+1);
  }

  std::cout << numberOfDivisors << std::endl;
  return 0;
}

This is an efficient solution:

#include <iostream>
int main() {
  int num = 20; 
  int numberOfDivisors = 1;

  for (int i = 2; i <= num; i++)
  {
    int exponent = 0;
    while (num % i == 0) {
        exponent++; 
        num /= i;
    }   
    numberOfDivisors *= (exponent+1);
  }

  std::cout << numberOfDivisors << std::endl;
  return 0;
}
佞臣 2024-07-12 23:43:06

在您致力于解决方案之前,请考虑在典型情况下筛选方法可能不是一个好的答案。

不久前有一个素数问题,我做了一个时间测试——对于 32 位整数,至少确定它是否是素数比暴力破解要慢。 有两个因素:

1)虽然人类需要一段时间才能进行除法运算,但他们在计算机上的速度非常快——类似于查找答案的成本。

2) 如果您没有素数表,您可以创建一个完全在 L1 缓存中运行的循环。 这使得速度更快。

Before you commit to a solution consider that the Sieve approach might not be a good answer in the typical case.

A while back there was a prime question and I did a time test--for 32-bit integers at least determining if it was prime was slower than brute force. There are two factors going on:

1) While a human takes a while to do a division they are very quick on the computer--similar to the cost of looking up the answer.

2) If you do not have a prime table you can make a loop that runs entirely in the L1 cache. This makes it faster.

小傻瓜 2024-07-12 23:43:05

一旦进行了质因数分解,就有一种方法可以找到约数的数量。 每个因子的每个指数加一,然后将指数相乘。

例如:
36
质因数分解:2^2*3^2
除数:1、2、3、4、6、9、12、18、36
除数数:9

每个指数加一 2^3*3^3
指数相乘:3*3 = 9

Once you have the prime factorization, there is a way to find the number of divisors. Add one to each of the exponents on each individual factor and then multiply the exponents together.

For example:
36
Prime Factorization: 2^2*3^2
Divisors: 1, 2, 3, 4, 6, 9, 12, 18, 36
Number of Divisors: 9

Add one to each exponent 2^3*3^3
Multiply exponents: 3*3 = 9

残龙傲雪 2024-07-12 23:43:05

你可以试试这个。 这有点hackish,但速度相当快。

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)

You might try this one. It's a bit hackish, but it's reasonably fast.

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)
浊酒尽余欢 2024-07-12 23:43:04

阿特金筛法是埃拉托色尼筛法的优化版本,它可以给出给定整数范围内的所有素数。 您应该能够通过谷歌搜索以获取更多详细信息。

一旦你有了这个列表,用你的数字除以每个素数来看看它是否是一个精确的除数(即余数为零)就很简单了。

计算数字(n)的除数的基本步骤是[这是从真实代码转换而来的伪代码,所以我希望我没有引入错误]:

for z in 1..n:
    prime[z] = false
prime[2] = true;
prime[3] = true;

for x in 1..sqrt(n):
    xx = x * x

    for y in 1..sqrt(n):
        yy = y * y

        z = 4*xx+yy
        if (z <= n) and ((z mod 12 == 1) or (z mod 12 == 5)):
            prime[z] = not prime[z]

        z = z-xx
        if (z <= n) and (z mod 12 == 7):
            prime[z] = not prime[z]

        z = z-yy-yy
        if (z <= n) and (x > y) and (z mod 12 == 11):
            prime[z] = not prime[z]

for z in 5..sqrt(n):
    if prime[z]:
        zz = z*z
        x = zz
        while x <= limit:
            prime[x] = false
            x = x + zz

for z in 2,3,5..n:
    if prime[z]:
        if n modulo z == 0 then print z

The sieve of Atkin is an optimized version of the sieve of Eratosthenes which gives all prime numbers up to a given integer. You should be able to google this for more detail.

Once you have that list, it's a simple matter to divide your number by each prime to see if it's an exact divisor (i.e., remainder is zero).

The basic steps calculating the divisors for a number (n) are [this is pseudocode converted from real code so I hope I haven't introduced errors]:

for z in 1..n:
    prime[z] = false
prime[2] = true;
prime[3] = true;

for x in 1..sqrt(n):
    xx = x * x

    for y in 1..sqrt(n):
        yy = y * y

        z = 4*xx+yy
        if (z <= n) and ((z mod 12 == 1) or (z mod 12 == 5)):
            prime[z] = not prime[z]

        z = z-xx
        if (z <= n) and (z mod 12 == 7):
            prime[z] = not prime[z]

        z = z-yy-yy
        if (z <= n) and (x > y) and (z mod 12 == 11):
            prime[z] = not prime[z]

for z in 5..sqrt(n):
    if prime[z]:
        zz = z*z
        x = zz
        while x <= limit:
            prime[x] = false
            x = x + zz

for z in 2,3,5..n:
    if prime[z]:
        if n modulo z == 0 then print z
森罗 2024-07-12 23:43:03

只需一行
我非常仔细地考虑了你的问题,并且尝试编写一段高效且高性能的代码
要在屏幕上打印给定数字的所有除数,我们只需要一行代码!
(通过 gcc 编译时使用选项 -std=c99)

for(int i=1,n=9;((!(n%i)) && printf("%d is a divisor of %d\n",i,n)) || i<=(n/2);i++);//n is your number

要查找除数的数量,您可以使用以下非常非常快的函数(适用于除 1 和 2 之外的所有整数),

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return counter;
}

或者如果您将给定数字视为除数(正确工作)对于除 1 和 2 之外的所有整数)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

注意:上述两个函数对于除数字 1 和 2 之外的所有正整数都可以正常工作
所以它适用于所有大于 2 的数字
但如果你需要覆盖 1 和 2 ,你可以使用以下函数之一(有点慢)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    if (n==2 || n==1)
    {
    return counter;
    }
    return ++counter;
}

或者

int number_of_divisors(int n)
{
    int counter,i;
for(counter=0,i=1;(!(i==n) && !(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

小就是美:)

JUST one line
I have thought very carefuly about your question and I have tried to write a highly efficient and performant piece of code
To print all divisors of a given number on screen we need just one line of code!
(use option -std=c99 while compiling via gcc)

for(int i=1,n=9;((!(n%i)) && printf("%d is a divisor of %d\n",i,n)) || i<=(n/2);i++);//n is your number

for finding numbers of divisors you can use the following very very fast function(work correctly for all integer number except 1 and 2)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return counter;
}

or if you treat given number as a divisor(work correctly for all integer number except 1 and 2)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

NOTE:two above functions works correctly for all positive integer number except number 1 and 2
so it is functional for all numbers that are greater than 2
but if you Need to cover 1 and 2 , you can use one of the following functions( a little slower)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    if (n==2 || n==1)
    {
    return counter;
    }
    return ++counter;
}

OR

int number_of_divisors(int n)
{
    int counter,i;
for(counter=0,i=1;(!(i==n) && !(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

small is beautiful :)

友谊不毕业 2024-07-12 23:43:02

这个有趣的问题比看起来要困难得多,而且还没有答案。 这个问题可以分解为两个截然不同的问题。

1 给定 N,找到 N 的质因数的列表 L

2 给定 L,计算唯一组合的数量

到目前为止我看到的所有答案都参考#1,但没有提到它对于巨大的数字来说并不容易处理。 对于中等大小的 N,甚至是 64 位数字,这很容易; 对于巨大的 N,因式分解问题可能需要“永远”。 公钥加密取决于此。

问题#2 需要更多讨论。 如果 L 只包含唯一的数字,则使用组合公式从 n 个项目中选择 k 个对象是一个简单的计算。 实际上,您需要将 k 从 1 变化到 sizeof(L) 时应用公式的结果相加。 然而,L 通常会包含多次出现的多个素数。 例如,L = {2,2,2,3,3,5}是N = 360的因式分解。现在这个问题相当困难!

重申#2,给定包含 k 个项目的集合 C,使得项目 a 有 a' 个重复项,项目 b 有 b' 个重复项,依此类推。有多少种 1 到 k-1 项的唯一组合? 例如,如果 L = {2,2,则 {2}、{2,2}、{2,2,2}、{2,3}、{2,2,3,3} 必须各自出现一次且仅出现一次,2,3,3,5}。 每个这样的唯一子集合是通过将子集合中的项目相乘得到的N的唯一除数。

This interesting question is much harder than it looks, and it has not been answered. The question can be factored into 2 very different questions.

1 given N, find the list L of N's prime factors

2 given L, calculate number of unique combinations

All answers I see so far refer to #1 and fail to mention it is not tractable for enormous numbers. For moderately sized N, even 64-bit numbers, it is easy; for enormous N, the factoring problem can take "forever". Public key encryption depends on this.

Question #2 needs more discussion. If L contains only unique numbers, it is a simple calculation using the combination formula for choosing k objects from n items. Actually, you need to sum the results from applying the formula while varying k from 1 to sizeof(L). However, L will usually contain multiple occurrences of multiple primes. For example, L = {2,2,2,3,3,5} is the factorization of N = 360. Now this problem is quite difficult!

Restating #2, given collection C containing k items, such that item a has a' duplicates, and item b has b' duplicates, etc. how many unique combinations of 1 to k-1 items are there? For example, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} must each occur once and only once if L = {2,2,2,3,3,5}. Each such unique sub-collection is a unique divisor of N by multiplying the items in the sub-collection.

寻找我们的幸福 2024-07-12 23:43:02

您问题的答案很大程度上取决于整数的大小。 对于小数字(例如小于 100 位)和大约 1000 位数字(例如在密码学中使用)的方法是完全不同的。

An answer to your question depends greatly on the size of the integer. Methods for small numbers, e.g. less then 100 bit, and for numbers ~1000 bit (such as used in cryptography) are completely different.

ぺ禁宫浮华殁 2024-07-12 23:43:01

这是一个直接的 O(sqrt(n)) 算法。 我用它来解决 project euler

def divisors(n):
    count = 2  # accounts for 'n' and '1'
    i = 2
    while i ** 2 < n:
        if n % i == 0:
            count += 2
        i += 1
    if i ** 2 == n:
        count += 1
    return count

Here is a straight forward O(sqrt(n)) algorithm. I used this to solve project euler

def divisors(n):
    count = 2  # accounts for 'n' and '1'
    i = 2
    while i ** 2 < n:
        if n % i == 0:
            count += 2
        i += 1
    if i ** 2 == n:
        count += 1
    return count

挽容 2024-07-12 23:43:00

我不同意阿特金筛法是可行的方法,因为检查 [1,n] 中每个数字的素数可能比通过除法减少数字要花费更长的时间。

下面是一些代码,虽然稍微有点黑客,但通常要快得多:

import operator
# A slightly efficient superset of primes.
def PrimesPlus():
  yield 2
  yield 3
  i = 5
  while True:
    yield i
    if i % 6 == 1:
      i += 2
    i += 2
# Returns a dict d with n = product p ^ d[p]
def GetPrimeDecomp(n):
  d = {}
  primes = PrimesPlus()
  for p in primes:
    while n % p == 0:
      n /= p
      d[p] = d.setdefault(p, 0) + 1
    if n == 1:
      return d
def NumberOfDivisors(n):
  d = GetPrimeDecomp(n)
  powers_plus = map(lambda x: x+1, d.values())
  return reduce(operator.mul, powers_plus, 1)

ps 这是解决这个问题的有效 python 代码。

I disagree that the sieve of Atkin is the way to go, because it could easily take longer to check every number in [1,n] for primality than it would to reduce the number by divisions.

Here's some code that, although slightly hackier, is generally much faster:

import operator
# A slightly efficient superset of primes.
def PrimesPlus():
  yield 2
  yield 3
  i = 5
  while True:
    yield i
    if i % 6 == 1:
      i += 2
    i += 2
# Returns a dict d with n = product p ^ d[p]
def GetPrimeDecomp(n):
  d = {}
  primes = PrimesPlus()
  for p in primes:
    while n % p == 0:
      n /= p
      d[p] = d.setdefault(p, 0) + 1
    if n == 1:
      return d
def NumberOfDivisors(n):
  d = GetPrimeDecomp(n)
  powers_plus = map(lambda x: x+1, d.values())
  return reduce(operator.mul, powers_plus, 1)

ps That's working python code to solve this problem.

单调的奢华 2024-07-12 23:42:58

@Yasky

你的除数函数有一个错误,它不能正确地处理完美的平方。

尝试:

int divisors(int x) {
    int limit = x;
    int numberOfDivisors = 0;

    if (x == 1) return 1;

    for (int i = 1; i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            if (limit != i) {
                numberOfDivisors++;
            }
            numberOfDivisors++;
        }
    }

    return numberOfDivisors;
}

@Yasky

Your divisors function has a bug in that it does not work correctly for perfect squares.

Try:

int divisors(int x) {
    int limit = x;
    int numberOfDivisors = 0;

    if (x == 1) return 1;

    for (int i = 1; i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            if (limit != i) {
                numberOfDivisors++;
            }
            numberOfDivisors++;
        }
    }

    return numberOfDivisors;
}
悲凉≈ 2024-07-12 23:42:58

与阿特金筛相比,还有更多的因式分解技术。 例如,假设我们想要分解 5893。那么它的 sqrt 是 76.76...现在我们尝试将 5893 写为平方的乘积。 那么 (77*77 - 5893) = 36 是 6 的平方,所以 5893 = 77*77 - 6*6 = (77 + 6)(77-6) = 83*71。 如果这不起作用,我们就会看看 78*78 - 5893 是否是一个完美的正方形。 等等。 使用这种技术,您可以比测试单个素数更快地快速测试 n 平方根附近的因子。 如果将这种排除大素数的技术与筛子结合起来,您将获得比单独使用筛子更好的因式分解方法。

这只是已开发的大量技术之一。 这是一个相当简单的问题。 例如,您需要花很长时间才能学习足够的数论来理解基于椭圆曲线的因式分解技术。 (我知道它们存在。我不理解它们。)

因此,除非您处理小整数,否则我不会尝试自己解决该问题。 相反,我会尝试找到一种方法来使用类似 PARI< /a> 库已经实现了高效的解决方案。 这样我就可以在大约 0.05 秒内分解出一个随机的 40 位数字,例如 124321342332143213122323434312213424231341。 (如果你想知道的话,它的因式分解是 29*439*1321*157907*284749*33843676813*4857795469949。我非常有信心它没有使用阿特金筛来解决这个问题......)

There are a lot more techniques to factoring than the sieve of Atkin. For example suppose we want to factor 5893. Well its sqrt is 76.76... Now we'll try to write 5893 as a product of squares. Well (77*77 - 5893) = 36 which is 6 squared, so 5893 = 77*77 - 6*6 = (77 + 6)(77-6) = 83*71. If that hadn't worked we'd have looked at whether 78*78 - 5893 was a perfect square. And so on. With this technique you can quickly test for factors near the square root of n much faster than by testing individual primes. If you combine this technique for ruling out large primes with a sieve, you will have a much better factoring method than with the sieve alone.

And this is just one of a large number of techniques that have been developed. This is a fairly simple one. It would take you a long time to learn, say, enough number theory to understand the factoring techniques based on elliptic curves. (I know they exist. I don't understand them.)

Therefore unless you are dealing with small integers, I wouldn't try to solve that problem myself. Instead I'd try to find a way to use something like the PARI library that already has a highly efficient solution implemented. With that I can factor a random 40 digit number like 124321342332143213122323434312213424231341 in about .05 seconds. (Its factorization, in case you wondered, is 29*439*1321*157907*284749*33843676813*4857795469949. I am quite confident that it didn't figure this out using the sieve of Atkin...)

素手挽清风 2024-07-12 23:42:56

德米特里是对的,你会希望阿特金筛生成素数列表,但我不认为这能解决整个问题。 现在您已经有了一个素数列表,您需要查看其中有多少素数充当除数(以及频率)。

这里有一些用于算法的 python 看这里并搜索“主题:数学 - 需要除数算法”。 只需计算列表中的项目数量,而不是返回它们。

这是数学博士< /a> 这解释了你到底需要用数学方法做什么。

本质上,它可以归结为您的号码 n 是否为:
n = a^x * b^y * c^z
(其中 a、b 和 c 是 n 的素因数,x、y 和 z 是除数重复的次数)
那么所有除数的总数是:
(x + 1) * (y + 1) * (z + 1)

编辑:顺便说一句,如果我理解正确的话,要找到 a、b、c 等,您将需要执行相当于贪婪算法的操作。 从最大的素因数开始,将其与自身相乘,直到进一步的乘法超过数字 n。 然后移动到下一个最低因子并乘以前一个素数 ^ 与当前素数相乘的次数,并继续乘以素数,直到下一个将超过 n...等等。跟踪您乘以除数在一起并将这些数字应用到上面的公式中。

不能 100% 确定我的算法描述,但如果不是的话,那就是类似的东西。

Dmitriy is right that you'll want the Sieve of Atkin to generate the prime list but I don't believe that takes care of the whole issue. Now that you have a list of primes you'll need to see how many of those primes act as a divisor (and how often).

Here's some python for the algo Look here and search for "Subject: math - need divisors algorithm". Just count the number of items in the list instead of returning them however.

Here's a Dr. Math that explains what exactly it is you need to do mathematically.

Essentially it boils down to if your number n is:
n = a^x * b^y * c^z
(where a, b, and c are n's prime divisors and x, y, and z are the number of times that divisor is repeated)
then the total count for all of the divisors is:
(x + 1) * (y + 1) * (z + 1).

Edit: BTW, to find a,b,c,etc you'll want to do what amounts to a greedy algo if I'm understanding this correctly. Start with your largest prime divisor and multiply it by itself until a further multiplication would exceed the number n. Then move to the next lowest factor and times the previous prime ^ number of times it was multiplied by the current prime and keep multiplying by the prime until the next will exceed n... etc. Keep track of the number of times you multiply the divisors together and apply those numbers into the formula above.

Not 100% sure about my algo description but if that isn't it it's something similar .

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