주어진 숫자의 제수를 계산하는 가장 최적의 알고리즘 (성능 측면)은 무엇입니까?
의사 코드 또는 예제에 대한 링크를 제공 할 수 있다면 좋을 것입니다.
편집 : 모든 답변이 매우 도움이되었습니다. 감사합니다. Atkin의 체를 구현하고 Jonathan Leffler가 지시 한 것과 비슷한 것을 사용할 것입니다. Justin Bozonier가 게시 한 링크에는 내가 원하는 것에 대한 추가 정보가 있습니다.
답변
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 % 확신 할 수는 없지만 그렇지 않은 경우 비슷한 내용입니다.
답변
있습니다 많은 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의 체를 사용하여 이것을 파악하지 못했다고 확신합니다.)
답변
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;
}
답변
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)
추신 :이 문제를 해결하기 위해 파이썬 코드를 사용하고 있습니다.
답변
다음은 간단한 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
답변
이 흥미로운 질문은보기보다 훨씬 어렵고 답이 없습니다. 질문은 두 가지 매우 다른 질문으로 구성 될 수 있습니다.
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의 고유 한 제수입니다.
답변
귀하의 질문에 대한 답변은 정수의 크기에 크게 의존합니다. 100 비트 이하의 작은 숫자와 ~ 1000 비트의 숫자 (암호화에 사용되는)의 방법은 완전히 다릅니다.
-
작고
n
유용한 참고 자료의 값 : A000005 : d (n) (tau (n) 또는 sigma_0 (n)이라고도 함), n의 제수 수 -
실제 예 : 정수 분해