В Википедии есть хороший список алгоритмов факторинга: http://en.wikipedia.org/wiki/Integer_factorization#Factoring_algorithms
Ваш второй подход эффективно использует сито и обладает хорошим свойством быстрого уменьшения проблемы, когда N кратно небольшому простому числу. Код может быть улучшен путем циклического перебора простых чисел, а не всех возможных делителей для 2..sqrt (n).
Кроме того, вы можете начать с теста первичности, чтобы вы знали, что N составная, прежде чем выполнять дополнительную работу.
В вашей заметке говорится, что вы не учитываете N, но проблемы связаны. Поиск F и R сводится к изучению непересекающихся комбинаций простых множителей N .
В случае N==36
начальная факторизация N равна 2, 2, 3, 3
. Коэффициенты F и R должны включать все из них (так, чтобы F*R==N
), и не может быть никакого перекрытия (так, чтобы GCD(F,R)==1
). Таким образом, 4 и 9 появляются немедленно.
Более поучительным примером может быть N==23256
. Его факторизация 2,2,2,3,3,17,19
. Поскольку не может быть перекрытия между F и R , каждая первичная база может входить только в одно из двух ведер (т.е. вы либо получаете все два, либо ни одного из них). Таким образом, мы можем сгруппировать факторы в 8,9,17,19
. Чтобы найти R, мы хотим, чтобы комбинация этих факторов была как можно большей, но ниже 152,49, квадратный корень из 23256. Наш выбор: {8}, {9}, {8,9}, {8,17} , {8,19}. Самый большой из них - 8*19
, что составляет 152. Соответствующее F равно 17*19
или 153.
варианты , перечисленные выше, вычисляются как [choice for choice in powerset([8,9,17,19]) if prod(choice) < math.sqrt(N)]
.
Таким образом, вся программа сводится к следующему:
prime_factors = factorize(N) # [2,2,2,3,3,17,19]
clusters = [p**e for p, e in collections.Counter(prime_factors).items()] # [8,9,17,19]
R = max(prod(group) for group in powerset(clusters) if prod(group) < math.sqrt(N))
F = N // R
Поиск powerset можно ускорить, обрезав генерацию наборов всякий раз, когда они превышают квадратный корень в N .
Имейте в виду, что факторизация требует больших вычислительных ресурсов, и наборы мощности растут очень быстро, но, вероятно, это гораздо менее трудоемко, чем запуск исходного алгоритма, который выполняет много делений, начиная с квадратного корня из N и работая вниз.