Найменш загальний нероздільник


11

В основному проблема полягає в тому, що для набору додатних чисел знайдіть мінімальне число яке не є дільником жодного елемента , тобто .SdSxS, dx

Позначимо n=|S|і C=max(S) . Розглянемо функцію F(x)= найменше просте число, яке не ділить x . Неважко помітити, що F(x)logx . А для безлічі S , нехай F(S)= найменше просте число , що не поділяє який - або елемент S . У нас верхня межа

F(S)F(lcm(S))F(Cn)nlogC.

Тому простий алгоритм грубої сили, який перераховує всі числа від 1 до nlogC і перевіряє, чи не він розділяє жоден елемент S , є многочленом і має часову складність O(n2logC) .

Інший спосіб вирішити проблему - обчислити всі фактори для кожного елемента S та використовувати їх у алгоритмі грубої сили, щоб перевірити, чи відповідає x у відповідь O(1) . Цей алгоритм має складність часу O(nmin(C,nlogC)+nlogC) і використовує O(nlogC) пам'ять, оскільки нам не потрібно обчислювати і магазин факторів більше , ніж nlogC . Для малих n і C вона працює краще.

Детально алгоритм складається з двох частин:

  1. Побудуйте набір S^ складається з усіх факторів усіх елементів S , тобто

    xS fnlogC, (fxfS^)
    Це можна зробити за час O(nmin(C,nlogC)) та O(nlogC) . (Звідки це походить? Для будь-якого елемента S ми можемо його розмістити за допомогою пробної факторизації з усіма числами до C або всіх простих чисел до nlogC , залежно від того, що менше; тому кожен елемент S може бути враховано за часом O(min(C,nlogC)) .)
  2. Знайдіть мінімальну кількість . Цей крок вимагає часу , якщо перевірити, чи можна виконати за час.dS^O(|S^|)=O(nlogC)xS^O(1)

У мене є два питання, які мене цікавлять:

  1. Чи існує швидший алгоритм вирішення проблеми?
  2. Як задано і , як можна побудувати множину з максимальним найменш спільним нероздільником?nCS

1. Під "попереднім обчисленням" я мав на увазі перед запуском алгоритму грубої сили. 2. Складність факторингу дійсно субекспоненціальное см Definiton з . C
SkyterX

@DW в точці 2, складність факторингу є субекспоненціальною щодо довжини бітового рядка, що представляє число, але SkyterX правильно говорить, що це , тобто пропорційний квадратному кореню розміру Кількість. O(C)
Lieuwe Vinkhuijzen

@LieuweVinkhuijzen, мені це не так. Складність факторингу з використанням GNFS буде приблизно такою, як , що значно менше . Див en.wikipedia.org/wiki / ... . O(exp{1.9(logC)1/3(loglogC)2/3})O(C)
DW

Заява про те, що другий метод працює краще "для малих і ", не зовсім правильне. Це краще, лише якщо . Таким чином, має бути великим, щоб другий метод мав ефективніше (не малий). nCnC/log(C)n
DW

@DW Ти маєш рацію, мені не було відомо про складність GNFS.
Lieuwe Vinkhuijzen

Відповіді:


6

Можна вдосконалити свій другий алгоритм, використовуючи кращі алгоритми для цілочислової факторизації.

Тут є два алгоритми цілочислової факторизації:

  • GNFS може множити ціле число з часом роботи .CO(LC[0.33,1.92])

  • ECM може знайти коефіцієнти (якщо такі є) із часом виконання ; знаходження всіх факторів займе разів довше (що порівняно мало в порівнянні з часом роботи ECM).nlogCO(LnlogC[0.5,1.41])O(logC/log(nlogC))

Тут .Ln[α,c]=exp{c(logn)α(loglogn)1α}

Це досить жахливий вираз за час роботи, але важливим фактом є те, що це швидше, ніж згадані вами методи. Зокрема, асимптотично набагато менший ніж , тобто GNFS набагато швидше, ніж спроба всіх можливих факторів . Також асимптотично значно менше , тобто ECM набагато швидше , ніж намагатися всі можливі чинники .LC[0.33,1.92]CCLnlogC[0.5,1.41]nlogCnlogC

Отже, загальний час роботи для цього методу приблизно , і це асимптотично краще, ніж ваш перший метод і асимптотично кращий, ніж ваш другий метод. Я не знаю, чи можна зробити ще краще.O~(nmin(LC[0.33,1.92],LnlogC[0.5,1.41]))


Я думаю, що будь-який швидкий алгоритм для цього завдання має включати в себе будь - то факторизации введення безліч . Я перевірю ці алгоритми факторизації, але все ще існує проблема їх належного тестування, яка піднімає другу проблему, про яку я згадав про побудову множини з максимальною відповіддю. SS
SkyterX

ECM знаходить один фактор у часі, який ви віддаєте. Якщо всі множники числа є ≤ n log C, то потрібно повторити алгоритм, аж до журналу C / log (n log C) разів.
gnasher729

3

Найменш поширений нероздільник може бути таким же великим, як N log C, але якщо N чисел розподілено випадковим чином, то найменший звичайний нероздільник, ймовірно, набагато менший, можливо, набагато менше, ніж N. Я буду будувати таблиці, з яких прайми - це дільники, числа яких.

На кожне просте число p у нас є індекс який означає, що всі числа до цього індексу були перевірені на подільність на p, і у нас є список усіх тих чисел, на які ділилися.kp

Тоді для d = 2, 3, 4, ... ми намагаємось знайти число, що ділиться на d, або показуємо, що його немає. Беремо найбільший простий коефіцієнт p d. Потім перевіряємо всі числа, які були ділими на p, чи вони також діляться на d. Якщо жодного не знайдено, ми перевіряємо подальші числа з індексами> на подільність на p, оновлення та список чисел, що ділиться на p, і перевіряємо, чи кожне число ділиться на d.kpkp

Щоб перевірити, чи є число, розділене на p, ми перевіряємо середні p числа. Пізніше, якщо ми перевіримо, чи є число, яке ділиться на 2p, є 50% шансів, що нам потрібно перевірити лише одне число (те, яке ділиться на p), і 50% шанс перевірити в середньому на 2p більше чисел. Знайти число, що ділиться на 3p, цілком ймовірно, швидко і так далі, і ми ніколи не перевіряємо більше, ніж N чисел на подільність на p, оскільки є лише N числа.

Я би сподівався, що це вийде з приблизно перевірок на роздільність.N2/logN

PS. Наскільки великим був би результат для випадкових чисел?

Припустимо, у мене є N випадкових чисел. Ймовірність того, що одне з N чисел ділиться на d, дорівнює 1 - (1 - 1 / d) ^ N. Я припускаю, що ймовірність того, що кожне з чисел 1 ≤ d ≤ k є коефіцієнтом одного з випадкових чисел, обчислюється шляхом множення цих ймовірностей (Ок, це трохи хиткий характер, оскільки ці ймовірності, ймовірно, не зовсім незалежні).

З таким припущенням, що при N = 1000 є 50% шансів, що одне з чисел 1..244 не розділить жодне число, а одне на мільярд, що кожне число до 507 ділить одне з чисел. З N = 10000 є 50% шансів, що одне з чисел 1..1726 не розділить жодне число, і одне на мільярд, що кожне число до 2979 ділить одне з чисел.

Я б запропонував, що для N випадкових входів розмір результату трохи більший, ніж N / ln N; можливо щось на кшталт N / ln N * (ln ln N) ^ 2. Ось чому:

Імовірність того, що щонайменше один з N випадкових чисел діляться на випадковий д становить . Якщо d - навколо N, то - приблизно 1 - exp (-1) ≈ 0,6321. Це для одного дільника; ймовірність того, що кожне з декількох чисел d ≈ N є дільником принаймні одного з N чисел, досить тонкі, тому максимальне d буде значно меншим за N.1(11/d)N1(11/d)N

Якщо d << N, то .1(11/d)N1exp(N/d)

Якщо d ≈ N / N , то пер .1exp(N/d)1exp(lnN)=11/N

Ми б додали ці ймовірності приблизно для N / ln N значень d, але для більшості d результат буде значно більшим, тому найбільший d буде якось більшим, ніж N / ln N, але значно менший за N.

PS. Пошук числа, що ділиться на d:

Вибираємо найбільший простий коефіцієнт p d, а потім спочатку вивчаємо числа, які, як відомо, ділилися на p. Скажіть d = kp. Тоді ми в середньому перевіряємо лише k числа, які поділяються на p, перевіряючи цей конкретний d, і перевіряємо не більше всіх N значень на подільність на p загалом, для всіх d ділимо на p. Власне, ми, швидше за все, перевіряємо менше N значень для більшості простих ліній p, оскільки після перевірки всіх N значень алгоритм, швидше за все, закінчується. Отже, якщо результат R, то я очікую, що менше N значень ділиться на кожне просте менше, ніж R. Якщо припустимо, R ≤ N, це приблизно N ^ 2 / log N перевірок.

PS. Запуск деяких тестів

Я кілька разів запускав цей алгоритм з N = 1 000 000 випадкових чисел> 0. Найменше поширений нероздільник був між 68 000 і 128 000, при цьому переважна більшість пробігів становить від 100 000 до 120 000. Кількість підрозділів становила від 520 до 1800 мільйонів, що набагато менше (N / ln N) ^ 2; більшість випадків використовували між 1000 і 1500 мільйонами підрозділів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.