주어진 수의 제수를 계산하는 알고리즘


177

주어진 숫자의 제수를 계산하는 가장 최적의 알고리즘 (성능 측면)은 무엇입니까?

의사 코드 또는 예제에 대한 링크를 제공 할 수 있다면 좋을 것입니다.

편집 : 모든 답변이 매우 도움이되었습니다. 감사합니다. Atkin의 체를 구현하고 Jonathan Leffler가 지시 한 것과 비슷한 것을 사용할 것입니다. Justin Bozonier가 게시 한 링크에는 내가 원하는 것에 대한 추가 정보가 있습니다.


여러 가지 요소가 필요한 요구 사항을 감안할 때 모호합니다. 나는 고유하지 않은 소수의 제수를 찾고 있다고 추측합니다. 코드를 원하지 않으면 인자로 계산할 숫자가 1이면 1을 반환하고 다른 것이 있으면 2를 반환하는 프로그램을 작성하십시오. 0 변경이 필요할 수 있습니다 ...
Justin Bozonier

@sker : 제수가 필요한 다양한 범위의 값이 있습니까? 요인을 계산하는 방법에는 여러 가지가 있으며 각 방법이 특정 범위에 더 적합합니다.
안데 터너

2
관련된 흥미로운 문제가 있습니다 projecteuler.net/problem=12
daniloquio

1
편집 된 Wikipedia 기사 에서조차 Atkin의 순진한 체질은 최대 비효율적 인 Eratosthenes의 체질보다 큰 비실용적 한계보다 빠르지 않으며 페이지 세그먼트 버전은 SoE에 더 유리합니다 (SoE primsieve 대 SoA primgen 참조 .. 그들의 연구가 빠르게 SOA를 입증하는 것이 일반적인 잘못된 인터넷 지식 Atkin의 파트너 번스타인에 의해 구현하지만, 인위적으로 SOE의 최적화가 이것을 증명하기 위해 사용 제한을 참조하십시오 내 SOA 응답 자세한 설명을위한
GordonBGood

답변:


78

Dmitriy는 Atkin의 체가 주요 목록을 생성하기를 원하지만 그것이 전체 문제를 처리한다고는 믿지 않습니다. 이제 소수 목록이 준비되었으므로 소수의 소수가 제수 역할을하는 빈도 (및 빈도)를 확인해야합니다.

다음은 algo에 대한 파이썬입니다. 여기 를보고 "제목 : 수학-제수 알고리즘 필요"를 검색 하십시오 . 그러나 목록에서 항목 수를 반환하는 대신 계산하십시오.

다음 은 수학적으로해야 할 일을 정확히 설명 하는 Dr. Math 입니다.

기본적으로 숫자 n가 다음과 같이 요약됩니다
n = a^x * b^y * c^z
(a, b 및 c는 n의 소수입니다 .x, y 및 z는 제수가 반복되는 횟수입니다). 그러면 모든 제수의 총 수는 다음과 같습니다.
(x + 1) * (y + 1) * (z + 1).

편집 : BTW, a, b, c 등을 찾으려면 이것을 올바르게 이해하고 있다면 욕심 많은 알고에 상당하는 것을하고 싶을 것입니다. 가장 큰 소수의 제수로 시작하여 추가 곱셈이 숫자 n을 초과 할 때까지 그 값을 곱합니다. 그런 다음 다음 가장 낮은 요소로 이동하고 이전 소수 ^ 현재 소수에 곱한 횟수를 곱하고 다음 소수가 n을 초과 할 때까지 소수를 계속 곱하십시오. 등. 제수를 모으고 위의 수식에 해당 숫자를 적용하십시오.

내 알고리즘 설명에 대해 100 % 확신 할 수는 없지만 그렇지 않은 경우 비슷한 내용입니다.


1
많은 수를 고려한다면 소수 목록 을 보지 않아도됩니다 . 가능한 빨리 모든 가능성을 제거하고 싶습니다! 자세한 내용은 내 대답을 참조하십시오.
user11318

나는 이것이 2 년 전인 것을 알고 있지만, 파이썬 알고리즘 링크가 끊어졌습니다. 지금 어디에 있는지 알고 있습니까?
jb.

2
n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)규칙도 마찬가지 입니다
SIslam

1
@Shashank이 말했듯이 "EDIT :"섹션의 알고리즘이 잘못되었습니다. n = 45 = 3 * 3 * 5라고 가정하십시오. 최대 소수의 제수는 5이지만 n을 초과 할 때까지이 값을 곱하면 5의 5 개 사본 (5 * 5 = 25 <45부터)의 2 개 사본이 알고리즘에보고됩니다.
j_random_hacker 2016 년

1
The Ateve of Atkin은 런타임 복잡도가 O (N / log (log (N)))입니다. 입니다. 1 ... Sqrt (n)에서 가능한 모든 제수를 검사하는 무차별 강제 실행은 O (Sqrt (N)) 의 런타임 복잡도를 갖습니다 . 이 답변은 어떻게 받아 들여졌습니까?
le_m

47

있습니다 많은 Atkin의 체보다는 인수에 더 기술. 예를 들어 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 라이브러리 와 같은 것을 사용하는 방법을 찾으려고 노력했습니다 . 그것으로 약 .05 초에 124321342332143213122323434312213424231341과 같은 임의의 40 자리 숫자를 고려할 수 있습니다. (당신이 궁금한 경우 인수 분해는 29 * 439 * 1132 * 157907 * 284749 * 33843676813 * 4857795469949입니다. Atkin의 체를 사용하여 이것을 파악하지 못했다고 확신합니다.)


1
당신은 기술이 매우 영리하지만 그 숫자가 얼마나 많은 요소를 가지고 있는지 말하지 않습니다.
sker

23
소인수 분해를 한 후에는 얼마나 많은 요소가 있는지 알아냅니다. 소인수가 p1, p2, ..., pk이고 m1, m2, ..., mk 번 반복된다고 가정합니다. 그런 다음 (1 + m1) (1 + m2) ... (1 + mk) 요소가 있습니다.
user11318

흥미로운 체는 2 차 체 입니다. 이것은 수 이론-2 차 합동과 선형 대수를 사용합니다. 나는 대학에서 2 학년 숫자 이론 과정에서 그것을 사용하기에 충분히 배웠습니다.
Tanner

33

Y

제수 함수에는 완벽한 제곱을 위해 올바르게 작동하지 않는 버그가 있습니다.

시험:

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;
}

6
i = 0 일 때 (x % i)가 0으로 나누지 않습니까? i = 1..limit해야합니까?
rhu

@rhu 0을 검사하는 것은 아무 의미가 없으므로 0은 의미가 없습니다.
EJoshuaS-복원 모니카

29

Atkin의 체는 갈 길이 멀다는 데 동의하지 않습니다. [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)

추신 :이 문제를 해결하기 위해 파이썬 코드를 사용하고 있습니다.


11

다음은 간단한 O (sqrt (n)) 알고리즘입니다. 나는 이것을 사용하여 프로젝트 오일러 를 해결 했습니다.

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

하지만 왜 항상 카운트를 2 씩 증가 시키는가?
SummerCode

3
sqrt (n)까지만 사용하기 때문입니다. 예를 들어, 36의 모든 제수를 찾으려면 2에서 6까지로 계산합니다. 1 & 36,2 & 18, 3 & 12, 4 & 9, 6,6은 모두 제수이며 쌍으로 나옵니다.
Antony Thomas

2
많은 Anthony에게 감사합니다, 나는 지금 이해했습니다 : D! 작은 부록 : sqrt (n) 값을 개별적으로 처리해야한다고 생각합니다. 왜냐하면 지금은 하나 대신 두 번 고려하기 때문입니다.
SummerCode

O (sqrt (n))는 그리 나쁘지 않지만 최적은 아닙니다. 소인수 분해 계산은 훨씬 빠르게 수행 할 수 있으며 제수의 수를 계산하기에 충분합니다.
le_m

반복 할 때마다 i²를 계산해야합니다. i를 √n (한 번만 계산)과 비교하는 것이 더 빠르지 않습니까?
Yukulélé

10

이 흥미로운 질문은보기보다 훨씬 어렵고 답이 없습니다. 질문은 두 가지 매우 다른 질문으로 구성 될 수 있습니다.

N이 1이면 N의 주요 요인 목록 L을 찾습니다.

주어진 L 2, 고유 조합 수 계산

지금까지 내가 본 모든 답변은 # 1을 언급하며 엄청난 숫자에 대해 다루기 힘든 것은 아닙니다. 중간 크기의 N, 심지어 64 비트 숫자의 경우에는 쉽습니다. 거대한 N의 경우, 인수 분해 문제는 "영원히"걸릴 수 있습니다. 공개 키 암호화는 이것에 달려 있습니다.

질문 # 2는 더 많은 토론이 필요합니다. L에 고유 한 숫자 만 포함 된 경우 n 개의 항목에서 k 개의 객체를 선택하기위한 조합 공식을 사용하는 간단한 계산입니다. 실제로 k를 1에서 sizeof (L)까지 변화시키면서 공식을 적용한 결과를 합산해야합니다. 그러나 L에는 일반적으로 여러 번의 여러 소수가 포함됩니다. 예를 들어, L = {2,2,2,3,3,5}는 N = 360의 인수 분해입니다. 이제이 문제는 매우 어렵습니다!

항목 a에 a '중복이 있고, 항목 b에 b'중복이있는 등 k 개의 항목을 포함하는 컬렉션 C에 대해 # 2를 휴식하는 것. 1에서 k-1 개의 항목의 고유 조합은 몇 개입니까? 예를 들어, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3}은 L = {2,2 인 경우 각각 한 번만 발생해야합니다. , 2,3,3,5}. 이러한 각 고유 하위 컬렉션은 하위 컬렉션의 항목을 곱하여 N의 고유 한 제수입니다.


여기 2. 매우 유사한 문제에 대한 일부 의사 코드에 대한 링크입니다 answers.google.com/answers/threadview/id/392914.html
mR_fr0g

3
질문 # 2에는 잘 알려진 해결책이 있습니다. 다중성 p_i을 가진 숫자의 주요 요소 인 {p_i, k_i}의 인수 분해의 k_i경우 해당 숫자의 총 제수는입니다 (k_1+1)*(k_2+1)*...*(k_n+1). 나는 당신이 지금까지 이것을 알고 있다고 생각하지만 무작위 독자라면 여기에 이익을 위해 이것을 적어 둡니다.
Will Ness


6

그냥 한 줄
나는 귀하의 질문에 대해 매우 신중하게 생각하고 매우 효율적이고 성능이 뛰어난 코드를 작성하려고했습니다. 주어진 숫자의 모든 제수를 화면에 인쇄하려면 한 줄의 코드 만 있으면됩니다! (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;
}

작습니다 :)


5

Atkin의 체는 모든 소수를 주어진 정수까지 제공하는 Eratosthenes 체의 최적화 된 버전입니다. 자세한 내용을 보려면 Google을 검색 할 수 있어야합니다.

일단 당신이 그 목록을 가지고 있다면, 숫자를 각 소수로 나누면 그것이 정확한 제수인지 알아볼 수 있습니다 (즉, 나머지는 0입니다).

숫자 (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

5

이걸 시도해보십시오. 약간 해킹이지만 합리적으로 빠릅니다.

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

2
이 함수는 합리적인 시간에 n의 주요 인자 분해를 제공하지만 a) 최적이 아니며 b) OP의 질문에 따라 주어진 수의 제수를 계산하지 않습니다
le_m

그리고 때문에 재귀의 큰 숫자에 대해 작동하지 않습니다
whackamadoodle3000

이것이 최적이 아니며 계수를 세는 것이 아니라 실제로 요인을 나열하지만 , 이것의 단순성과 아름다움은 놀랍고 합리적입니다. ^^
Gaurav Singhal

5

소인수 분해를하면 제수를 구할 수있는 방법이 있습니다. 각 개별 요인에 대해 각 지수에 1을 더한 다음 지수를 곱하십시오.

예 : 36 소인수 분해 : 2 ^ 2 * 3 ^ 2 제수 : 1, 2, 3, 4, 6, 9, 12, 18, 36 제수 : 9

각 지수에 1을 더합니다 2 ^ 3 * 3 ^ 3 지수를 곱하기 : 3 * 3 = 9


3

솔루션을 커밋하기 전에 Sieve 접근 방식이 일반적인 경우에 적합하지 않을 수 있습니다.

얼마 전 주요한 질문이 있었고 시간 테스트를 수행했습니다. 최소한 소수가 무차별보다 느린 지 여부를 결정하는 32 비트 정수를 테스트했습니다. 두 가지 요인이 진행됩니다.

1) 사람이 부서를 수행하는 데 시간이 걸리지 만 답변을 찾는 데 드는 비용과 비슷한 컴퓨터에서 매우 빠릅니다.

2) 소수 테이블이 없으면 L1 캐시에서 완전히 실행되는 루프를 만들 수 있습니다. 이것은 더 빨라집니다.


3

이것은 효율적인 솔루션입니다.

#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;
}

2

제수는 놀라운 일을합니다. 숫자에 대한 제수의 수를 확인 n하려면 전체 스펙트럼에 걸쳐 중복되는 것이 분명 1...n합니다. 나는 이것에 대한 심도있는 연구를하지 않았지만 삼각형 숫자에 관한 프로젝트 오일러의 문제 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;
}

모든 알고리즘에는 약점이 있습니다. 나는 이것이 소수에 대해 약하다고 생각했다. 그러나 삼각형 숫자는 인쇄되지 않았기 때문에 그 목적을 완벽하게 달성했습니다. 내 프로파일 링에서 꽤 잘했다고 생각합니다.

행복한 휴일.


1
첫 번째 반복에서 0으로 나누기
barfoon

불행히도. ++ 난 (으로 나누기 오류가 발생할 것이다) ++ I 다르다
iGbanam

PHP로 함수를 작성하고 실행했습니다. 여기 내가 가진 것 -i.minus.com/iKzuSXesAkpbp.png
barfoon

이상한 이유로, 이것은 나를 위해 완벽하게 작동했습니다. 잘, 내 나쁜. 시작 numberOfDivisors과 반복자 1에서; 이것은 0으로 나누기 오류를 제거해야합니다
iGbanam

1
알고리즘이 완벽한 제곱을 위해 작동하지 않습니다. 예를 들어, 입력 x = 4에 대해 2를 두 번 계산하기 때문에 4를 반환합니다. 1, 2, 2, 4입니다. 답은 3 : 1,2,4
Michael

1

Atkin의 체를 원한다면 여기에 설명되어 있습니다 : http://en.wikipedia.org/wiki/Sieve_of_Atkin


1
그것은 주어진 숫자 이하의 소수를 얻을 것입니다-그러나 그 소수가 제수가 될 것이라는 보장은 없습니다? (내가 빠진 것이 아니라면)
Andrew Edgecombe

그것은 균등 N.를 분할 여기에서 모든 소수 <SQRT (N)를 찾는 빠른 도약
SquareCog

1
빠른 도약 일 수 있지만 모든 프라임 <sqrt (N)을 테스트하는 것은 아무리 효율적으로 찾을 수 있더라도 여전히 잘못된 팩토링 기법입니다. 이를 개선 할 수있는 방법이 많이 있습니다.
user11318

소수를 테스트하는 것은 O (N)이며 어려운 부분을 찾는 것입니다. 그러나 에라토스테네스의 최적화되지 않은 체로도 몇 초 안에 수백만 미만의 모든 소수를 찾을 수 있습니다. 덮 어떤 64B 번호, 나는 확실히 우리는 여기에 인수 암호화 수준의 물건에 대해 얘기하지 않을거야
매튜 Scharley

1

소수 방법은 여기에서 매우 명확합니다. 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  .

1

숫자 이론 교과서는 제수 계산 함수 tau를 호출합니다. 첫 번째 흥미로운 사실은 그것이 곱셈이라는 것입니다. a와 b에 공통 인자가없는 경우 τ (ab) = τ (a) τ (b)입니다. (증명 : a와 b의 각 제수 쌍은 ab의 고유 제수를 제공합니다).

pa 소수의 경우, τ (p ** k) = k + 1 (p의 거듭 제곱)입니다. 따라서 인수 분해에서 τ (n)을 쉽게 계산할 수 있습니다.

그러나 많은 수의 분해는 느릴 수 있습니다 (RSA crytopraphy의 보안은 분해하기 어려운 두 개의 큰 소수의 곱에 달려 있습니다). 이 최적화 된 알고리즘을 제안합니다

  1. 숫자가 소수인지 테스트합니다 (빠름).
  2. 그렇다면 2를 반환하십시오.
  3. 그렇지 않으면 숫자를 인수 분해합니다 (여러 개의 큰 소수 인 경우 느림)
  4. 인수 분해에서 τ (n) 계산

1

다음은 주어진 수의 제수를 찾는 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++)
{
    ...
}

1

내가 쓴 함수는 다음과 같습니다. 최악의 시간 복잡도는 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;
}

이 함수가 무엇을 계산하는지 모르지만 n의 제수 목록은 아닙니다.
le_m

1

이것이 숫자 제수를 계산하는 가장 기본적인 방법입니다.

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);

    }
}

1

K

코드를 테스트하고 약간 개선했지만 이제는 더 빠릅니다. 나는 또한 @ هومن جاویدپور 코드로 테스트했는데, 이것은 그의 코드보다 빠릅니다.

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;
}

0

이것은 숫자를 인수 분해하는 것의 문제가 아닌 숫자의 모든 요소를 ​​결정합니까? 그런 다음 하나 이상의 요인의 모든 조합이 필요한지 여부를 결정할 수 있습니다.

따라서 가능한 알고리즘은 다음과 같습니다.

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

그러면 나머지 답변을 결정하기 위해 요인을 결합하는 것은 귀하의 몫입니다.


0

이것은 저스틴의 대답을 바탕으로 내가 생각해 낸 것입니다. 최적화가 필요할 수 있습니다.

n=int(input())

a=[]
b=[]

def sieve(n):
    np = n + 1
    s = list(range(np)) 
    s[1] = 0
    sqrtn = int(n**0.5)
    for i in range(2, sqrtn + 1): 
        if s[i]:
            s[i*i: np: i] = [0] * len(range(i*i, np, i))
    return filter(None, s)

k=list(sieve(n))

for i in range(len(k)):
        if n%k[i]==0:
                a.append(k[i])

a.sort()

for i in range(len(a)):
        j=1
        while n%(a[i]**j)==0: 
                j=j+1
        b.append(j-1)

nod=1

for i in range(len(b)):
        nod=nod*(b[i]+1)

print('no.of divisors of {} = {}'.format(n,nod))

0

나는 이것이 당신이 찾고있는 것이라고 생각합니다. 메모장에 복사하여 붙여 넣기 * *로 저장하십시오.

Pls는 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

882161280-1282 제수
dondon

0

나는 이것이 정확하고 편리 할 것이라고 생각합니다.

script.pyton

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


0

이 라인을 따라 무언가를 시도하십시오.

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;
}

-1

가장 효율적인 방법을 모르지만 다음을 수행합니다.

  • 소수의 제곱근 이하의 모든 소수를 찾기 위해 소수 테이블을 만듭니다 (개인적으로 Atkin의 체를 사용합니다)
  • 모든 소수를 숫자의 제곱근 이하로 세고 2를 곱하십시오. 숫자의 제곱근이 정수이면 카운트 변수에서 1을 빼십시오.

작동해야합니다 \ o /

필요한 경우 내일 C로 코딩하여 시연 할 수 있습니다.


2
혼란 스러워요. 숫자의 제곱근보다 작은 소수를 모두 세어도 제수가되지는 않습니다. 숫자의 제곱근보다 작은 모든 소수가 해당 숫자의 제수가 될 수는 없습니다.
개렛 버그
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.