Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6085
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Алгоритм нахождения наибольшего простого множителя числа
Каков наилучший подход к вычислению наибольшего простого множителя числа?
Я думаю, что наиболее эффективным будет следующее:
- Найти наименьшее простое число, которое делится чисто
- Проверьте, является ли результат деления простым
- Если нет, найдите следующий самый низкий
- Перейти к 2.
Я основываю это предположение на том, что легче вычислить малые простые множители. Разве это правильно? Какие еще подходы я должен рассмотреть?
Edit: теперь я понял, что мой подход бесполезен, если в игре есть более 2 простых множителей, поскольку Шаг 2 терпит неудачу, когда результат является произведением двух других простых чисел, поэтому необходим рекурсивный алгоритм.
Правка снова: и теперь я понял, что это все еще работает, потому что последнее найденное простое число должно быть самым высоким, поэтому любая дальнейшая проверка не-простого результата из шага 2 приведет к меньшему простому числу.
Вот лучший алгоритм, который я знаю (в Python)
def prime_factors(n):
"""Returns all the prime factors of a positive integer"""
factors = []
d = 2
while n > 1:
while n % d == 0:
factors.append(d)
n /= d
d = d + 1
return factors
pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list
Приведенный выше метод работает в O(n) в худшем случае (когда входное число является простым числом).
EDIT:
Ниже приводится версия O(sqrt(n)) , предложенная в комментарии. Вот вам еще один код.
def prime_factors(n):
"""Returns all the prime factors of a positive integer"""
factors = []
d = 2
while n > 1:
while n % d == 0:
factors.append(d)
n /= d
d = d + 1
if d*d > n:
if n > 1: factors.append(n)
break
return factors
pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list
На самом деле есть несколько более эффективных способов найти коэффициенты больших чисел (для меньших пробное деление работает достаточно хорошо).
Один из методов, который очень быстр, если входное число имеет два фактора, очень близких к его квадратному корню, известен как факторизация ферма . Он использует тождество N = (a + b) (a - b) = a^2 - b^2 и прост в понимании и реализации. К сожалению, это не очень быстро в целом.
Наиболее известным методом факторинга чисел длиной до 100 знаков является квадратичное сито . В качестве бонуса, часть алгоритма легко выполняется с параллельной обработкой.
Еще один алгоритм, о котором я слышал, - это алгоритм Ро Полларда . Это не так эффективно, как квадратичное сито в целом, но кажется, что его легче реализовать.
Как только вы решите, как разделить число на два фактора, вот самый быстрый алгоритм, который я могу придумать, чтобы найти самый большой простой фактор числа:
Создайте приоритетную очередь, в которой изначально хранится сам номер. На каждой итерации вы удаляете самое большое число из очереди и пытаетесь разделить его на два фактора (не допуская, чтобы 1 был одним из этих факторов, конечно). Если этот шаг не удается, число является простым, и у вас есть свой ответ! В противном случае вы добавляете два фактора в очередь и повторяете.
Мой ответ основан на триптихе, но значительно улучшает его. Он основан на том факте, что за пределами 2 и 3 все простые числа имеют вид 6n-1 или 6n+1.
var largestPrimeFactor;
if(n mod 2 == 0)
{
largestPrimeFactor = 2;
n = n / 2 while(n mod 2 == 0);
}
if(n mod 3 == 0)
{
largestPrimeFactor = 3;
n = n / 3 while(n mod 3 == 0);
}
multOfSix = 6;
while(multOfSix - 1 <= n)
{
if(n mod (multOfSix - 1) == 0)
{
largestPrimeFactor = multOfSix - 1;
n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
}
if(n mod (multOfSix + 1) == 0)
{
largestPrimeFactor = multOfSix + 1;
n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
}
multOfSix += 6;
}
Недавно я написал статью в блоге , объясняющую, как работает этот алгоритм.
Я бы рискнул предположить, что метод, в котором нет необходимости в тесте на примитивность (и нет конструкции сита), будет работать быстрее, чем тот, который использует их. Если это так, то это, вероятно, самый быстрый алгоритм здесь.
Код JavaScript:
'option strict';
function largestPrimeFactor(val, divisor = 2) {
let square = (val) => Math.pow(val, 2);
while ((val % divisor) != 0 && square(divisor) <= val) {
divisor++;
}
return square(divisor) <= val
? largestPrimeFactor(val / divisor, divisor)
: val;
}
пример использования:
let result = largestPrimeFactor(600851475143);
Самое простое решение - это пара взаимно рекурсивных функций.
Первая функция генерирует все простые числа:
- Начните со списка всех натуральных чисел, превышающих 1.
- Удалите все числа, которые не являются простыми. То есть числа, которые не имеют простых множителей (кроме самих себя). Увидеть ниже.
Вторая функция возвращает простые множители заданного числа n в порядке возрастания.
- Возьмите список всех простых чисел (см. выше).
- Удалите все числа, которые не являются факторами
n.
Самый большой простой множитель n - это последнее число, заданное второй функцией.
Этот алгоритм требует наличия ленивого списка или языка (или структуры данных) с семантикой call-by-need .
Для уточнения приведем одну (неэффективную) реализацию вышесказанного в Haskell:
import Control.Monad
-- All the primes
primes = 2 : filter (ap (<=) (head . primeFactors)) [3,5..]
-- Gives the prime factors of its argument
primeFactors = factor primes
where factor [] n = []
factor xs@(p:ps) n =
if p*p > n then [n]
else let (d,r) = divMod n p in
if r == 0 then p : factor xs d
else factor ps n
-- Gives the largest prime factor of its argument
largestFactor = last . primeFactors
Чтобы сделать это быстрее , просто нужно быть более умным в определении того, какие числа являются простыми и/или коэффициентами n, но алгоритм остается прежним.
Все числа могут быть выражены как произведение простых чисел, например:
102 = 2 x 3 x 17
712 = 2 x 2 x 2 x 89
Вы можете найти их, просто начав с 2 и просто продолжая делить, пока результат не станет кратным вашему числу:
712 / 2 = 356 .. 356 / 2 = 178 .. 178 / 2 = 89 .. 89 / 89 = 1
используя этот метод, вам не нужно на самом деле вычислять какие-либо простые числа: все они будут простыми, основываясь на том факте, что вы уже факторизировали число как можно больше со всеми предыдущими числами.
number = 712;
currNum = number; // the value we'll actually be working with
for (currFactor in 2 .. number) {
while (currNum % currFactor == 0) {
// keep on dividing by this number until we can divide no more!
currNum = currNum / currFactor // reduce the currNum
}
if (currNum == 1) return currFactor; // once it hits 1, we're done.
}
//this method skips unnecessary trial divisions and makes
//trial division more feasible for finding large primes
public static void main(String[] args)
{
long n= 1000000000039L; //this is a large prime number
long i = 2L;
int test = 0;
while (n > 1)
{
while (n % i == 0)
{
n /= i;
}
i++;
if(i*i > n && n > 1)
{
System.out.println(n); //prints n if it's prime
test = 1;
break;
}
}
if (test == 0)
System.out.println(i-1); //prints n if it's the largest prime factor
}
//this method skips unnecessary trial divisions and makes
//trial division more feasible for finding large primes
public static void main(String[] args)
{
long n= 1000000000039L; //this is a large prime number
long i = 2L;
int test = 0;
while (n > 1)
{
while (n % i == 0)
{
n /= i;
}
i++;
if(i*i > n && n > 1)
{
System.out.println(n); //prints n if it's prime
test = 1;
break;
}
}
if (test == 0)
System.out.println(i-1); //prints n if it's the largest prime factor
}
Я знаю, что это не быстрое решение. Постинг, как мы надеемся, легче понять медленное решение.
public static long largestPrimeFactor(long n) {
// largest composite factor must be smaller than sqrt
long sqrt = (long)Math.ceil(Math.sqrt((double)n));
long largest = -1;
for(long i = 2; i <= sqrt; i++) {
if(n % i == 0) {
long test = largestPrimeFactor(n/i);
if(test > largest) {
largest = test;
}
}
}
if(largest != -1) {
return largest;
}
// number is prime
return n;
}
n = abs(number);
result = 1;
if (n mod 2 == 0) {
result = 2;
while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
if (n mod i == 0) {
result = i;
while (n mod i = 0) n /= i;
}
}
return max(n,result)
n = abs(number);
result = 1;
if (n mod 2 == 0) {
result = 2;
while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
if (n mod i == 0) {
result = i;
while (n mod i = 0) n /= i;
}
}
return max(n,result)
Есть некоторые тесты по модулю, которые являются сверхплотными, так как n никогда не может быть разделено на 6, если все факторы 2 и 3 были удалены. Вы могли бы разрешить только простые числа для i, что показано в нескольких других ответах здесь.
Вы могли бы на самом деле переплетаются решето Эратосфена здесь:
- Сначала создайте список целых чисел вверх к sqrt (n).
- В цикле for отметьте все кратные числа от i до Нового sqrt (n) как не prime, и используйте вместо этого цикл while.
- я до следующего простого числа в список.
Также смотрите этот вопрос .
Python итерационный подход путем удаления всех простых множителей из числа
def primef(n):
if n <= 3:
return n
if n % 2 == 0:
return primef(n/2)
elif n % 3 ==0:
return primef(n/3)
else:
for i in range(5, int((n)**0.5) + 1, 6):
#print i
if n % i == 0:
return primef(n/i)
if n % (i + 2) == 0:
return primef(n/(i+2))
return n
Я использую алгоритм, который продолжает делить число на его текущий простой коэффициент.
Мое решение в python 3 :
def PrimeFactor(n):
m = n
while n%2==0:
n = n//2
if n == 1: # check if only 2 is largest Prime Factor
return 2
i = 3
sqrt = int(m**(0.5)) # loop till square root of number
last = 0 # to store last prime Factor i.e. Largest Prime Factor
while i <= sqrt :
while n%i == 0:
n = n//i # reduce the number by dividing it by it's Prime Factor
last = i
i+=2
if n> last: # the remaining number(n) is also Factor of number
return n
else:
return last
print(PrimeFactor(int(input())))
Вход: 10
Выход: 5
Вход: 600851475143
Выход: 6857
Вот моя попытка в c#. последняя распечатка - это самый большой простой множитель числа. Я проверил, и это работает.
namespace Problem_Prime
{
class Program
{
static void Main(string[] args)
{
/*
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
*/
long x = 600851475143;
long y = 2;
while (y < x)
{
if (x % y == 0)
{
// y is a factor of x, but is it prime
if (IsPrime(y))
{
Console.WriteLine(y);
}
x /= y;
}
y++;
}
Console.WriteLine(y);
Console.ReadLine();
}
static bool IsPrime(long number)
{
//check for evenness
if (number % 2 == 0)
{
if (number == 2)
{
return true;
}
return false;
}
//don't need to check past the square root
long max = (long)Math.Sqrt(number);
for (int i = 3; i <= max; i += 2)
{
if ((number % i) == 0)
{
return false;
}
}
return true;
}
}
}
Вычисляет наибольший простой множитель числа с помощью рекурсии в C++. Работа кода объясняется ниже:
int getLargestPrime(int number) {
int factor = number; // assumes that the largest prime factor is the number itself
for (int i = 2; (i*i) <= number; i++) { // iterates to the square root of the number till it finds the first(smallest) factor
if (number % i == 0) { // checks if the current number(i) is a factor
factor = max(i, number / i); // stores the larger number among the factors
break; // breaks the loop on when a factor is found
}
}
if (factor == number) // base case of recursion
return number;
return getLargestPrime(factor); // recursively calls itself
}
Вот мой подход к быстрому вычислению самого большого простого множителя.
Он основан на том, что модифицированный x не содержит непервичных факторов. Чтобы достичь этого, мы делим x , как только фактор найден. Тогда остается только вернуть самый большой фактор. Это будет уже Прайм.
Код (Haskell):
f max' x i | i > x = max'
| x `rem` i == 0 = f i (x `div` i) i -- Divide x by its factor
| otherwise = f max' x (i + 1) -- Check for the next possible factor
g x = f 2 x 2
Следующий алгоритм C++ не самый лучший, но он работает для чисел меньше миллиарда и довольно быстро
#include <iostream>
using namespace std;
// ------ is_prime ------
// Determines if the integer accepted is prime or not
bool is_prime(int n){
int i,count=0;
if(n==1 || n==2)
return true;
if(n%2==0)
return false;
for(i=1;i<=n;i++){
if(n%i==0)
count++;
}
if(count==2)
return true;
else
return false;
}
// ------ nextPrime -------
// Finds and returns the next prime number
int nextPrime(int prime){
bool a = false;
while (a == false){
prime++;
if (is_prime(prime))
a = true;
}
return prime;
}
// ----- M A I N ------
int main(){
int value = 13195;
int prime = 2;
bool done = false;
while (done == false){
if (value%prime == 0){
value = value/prime;
if (is_prime(value)){
done = true;
}
} else {
prime = nextPrime(prime);
}
}
cout << "Largest prime factor: " << value << endl;
}
Простой фактор с использованием сита :
#include <bits/stdc++.h>
using namespace std;
#define N 10001
typedef long long ll;
bool visit[N];
vector<int> prime;
void sieve()
{
memset( visit , 0 , sizeof(visit));
for( int i=2;i<N;i++ )
{
if( visit[i] == 0)
{
prime.push_back(i);
for( int j=i*2; j<N; j=j+i )
{
visit[j] = 1;
}
}
}
}
void sol(long long n, vector<int>&prime)
{
ll ans = n;
for(int i=0; i<prime.size() || prime[i]>n; i++)
{
while(n%prime[i]==0)
{
n=n/prime[i];
ans = prime[i];
}
}
ans = max(ans, n);
cout<<ans<<endl;
}
int main()
{
ll tc, n;
sieve();
cin>>n;
sol(n, prime);
return 0;
}
Мне кажется, что шаг #2 данного алгоритма не будет таким уж эффективным подходом. У вас нет никаких разумных ожиданий, что он является первичным.
Кроме того, предыдущий ответ, предполагающий сито Эратосфена, совершенно неверен. Я только что написал две программы для factor 123456789. Один был основан на сите, другой был основан на следующем:
1) Test = 2
2) Current = Number to test
3) If Current Mod Test = 0 then
3a) Current = Current Div Test
3b) Largest = Test
3c) Goto 3.
4) Inc(Test)
5) If Current < Test goto 4
6) Return Largest
Эта версия была в 90 раз быстрее сита.
Дело в том, что на современных процессорах тип операции имеет гораздо меньшее значение, чем количество операций, не говоря уже о том, что алгоритм выше может работать в кэше, а сито-нет. сито использует много операций, вычеркивая все составные числа.
Заметьте также,что мое разделение факторов по мере их выявления сокращает пространство, которое должно быть проверено.
С Java:
Для значений int :
public static int[] primeFactors(int value) {
int[] a = new int[31];
int i = 0, j;
int num = value;
while (num % 2 == 0) {
a[i++] = 2;
num /= 2;
}
j = 3;
while (j <= Math.sqrt(num) + 1) {
if (num % j == 0) {
a[i++] = j;
num /= j;
} else {
j += 2;
}
}
if (num > 1) {
a[i++] = num;
}
int[] b = Arrays.copyOf(a, i);
return b;
}
Для значений long :
static long[] getFactors(long value) {
long[] a = new long[63];
int i = 0;
long num = value;
while (num % 2 == 0) {
a[i++] = 2;
num /= 2;
}
long j = 3;
while (j <= Math.sqrt(num) + 1) {
if (num % j == 0) {
a[i++] = j;
num /= j;
} else {
j += 2;
}
}
if (num > 1) {
a[i++] = num;
}
long[] b = Arrays.copyOf(a, i);
return b;
}
Это вероятно не всегда быстрее но более оптимистично о том что вы находите большой простой делитель:
N- это ваш номер- Если это простое число, то
return(N) - Вычислять простые числа вплоть до
Sqrt(N) - Пройдите через простые числа в порядке убывания (самый большой первый)
- Если
N is divisible by Prime, тоReturn(Prime)
- Если
Правка: на Шаге 3 Вы можете использовать сито Эратосфена или сито Аткинса или что угодно еще, но само по себе сито не найдет для вас самого большого первичного фактора. (Вот почему я бы не выбрал пост SQLMenace в качестве официального ответа...)
Я думаю, что было бы хорошо хранить где-то все возможные простые числа меньше n и просто перебирать их, чтобы найти самый большой делитель. Вы можете получить простые числа из числа prime-numbers.org .
Конечно я предполагаю что ваш номер не слишком большой :)