Алгоритм обчислення кількості дільників заданого числа


177

Який був би найоптимальніший алгоритм (продуктивний) для обчислення кількості дільників даного числа?

Буде чудово, якщо ви можете надати псевдокод або посилання на якийсь приклад.

EDIT: Усі відповіді були дуже корисними, дякую. Я впроваджую Сито Аткіна, а потім я буду використовувати щось подібне до того, що вказав Джонатан Леффлер. Посилання, розміщене Джастіном Бозоньє, містить додаткову інформацію про те, що я хотів.


Зважаючи на те, що ваші запитання приходять з кількістю факторів, невизначені. Я здогадуюсь, що ви шукаєте кількість не унікальних простих дільників, тому що якщо ви цього не хочете, я просто напишу програму, щоб завжди повертати 1, якщо число до коефіцієнта - одне і 2, якщо це щось інше. 0 може знадобитися зміна ...
Джастін Бозоньє,

@sker: Чи існує діапазон значень, для якого вам потрібні дільники. Існує багато способів обчислення факторів, і кожен метод краще підходить до певного діапазону.
Ande Turner

2
Ось пов'язана цікава проблема projecteuler.net/problem=12
daniloquio

1
Наївне сито Аткіна навіть із відредагованої статті Вікіпедії ніколи не буде швидшим, ніж максимально розподілене колесом сито Ератостена до величезних непрактичних меж, а версії сегментованої сторінки навіть більше корисні для SoE (див. SoE primesieve versus SoA primegen як .. здійснюється партнером Аткін в Bernstein це загальне неправильне знання Інтернету , що їх дослідження довело SoA швидше, але вони штучно обмежила оптимізація СОС використовується для того , щоб це довести Дивіться мій SoA відповідь для подальшого пояснення
GordonBGood

Відповіді:


78

Дмитро має рацію, що ви хочете, щоб Сіто Аткіна створило першочерговий список, але я не вірю, що це стосується всієї проблеми. Тепер, коли у вас є список простих ліній, вам потрібно буде побачити, скільки цих праймерів діють як дільник (і як часто).

Ось якийсь пітон для альго. Подивіться тут і шукайте "Тема: математика - потрібен алгоритм ділення". Просто порахуйте кількість елементів у списку, а не повертайте їх.

Ось доктор Мат, який пояснює, що саме вам потрібно зробити математично.

По суті, воно зводиться до того, якщо ваше число 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
Якщо ви маєте велику кількість, вам навіть не хочеться дивитись на основний список. Ви хочете якнайшвидше усунути цілий спектр можливостей! Дивіться мою відповідь для отримання додаткової інформації.
користувач11318

Я усвідомлюю, що це було 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, призведе до того, що алгоритм повідомляє, що у нього є 2 копії фактора 5 (оскільки 5 * 5 = 25 <45).
j_random_hacker

1
"Сито Аткіна" в кращому випадку має складність виконання O (N / log (log (N))) . Груба сила, що перевіряє всі можливі дільники від 1 ... Sqrt (n), має складність виконання O (Sqrt (N)), яка набагато перевершує. Звідки ця відповідь була прийнята?
le_m

47

Існує набагато більше прийомів факторингу, ніж сито Аткіна. Наприклад, припустимо, що ми хочемо ввести коефіцієнт 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, у якому вже реалізовано високоефективне рішення. Завдяки цьому я можу підрахувати випадкове 40-розрядне число, наприклад 124321342332143213122323434312213424231341 приблизно за 0,05 секунди. (Його факторизація, якщо ви задумалися, становить 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Я впевнений, що цього не зрозумів, використовуючи сито Аткіна ...)


1
Ти техніка дуже розумна, але це не говорить мені, скільки факторів має число, чи не так?
sker

23
Після того, як у вас є основна факторизація, з'ясування того, скільки факторів є простим. Припустимо, прості коефіцієнти - p1, p2, ..., pk, і вони повторюються m1, m2, ..., mk разів. Тоді є (1 + m1) (1 + m2) ... (1 + mk) фактори.
користувач11318

Цікавим ситом є квадратичне сито . Тут використовується теорія чисел - квадратичні конгруенції та деяка лінійна алгебра. Я досить навчився використовувати його на курсі теорії чисел на другому курсі в університеті.
Таннер

33

@Yasky

Ваша функція дільників має помилку в тому, що вона не працює правильно для ідеальних квадратів.

Спробуйте:

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
Не спричинить (x% i) ділення на нуль, коли i = 0? я повинен = 1..обмежити?
rhu

@rhu Перевірка 0 в будь-якому разі є безглуздою, оскільки 0 не є фактором жодного числа.
EJoshuaS

29

Я не погоджуюся з тим, що сито Аткіна - це дорога, тому що перевірити кожне число в [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)

ps Це працює код python для вирішення цієї проблеми.


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 - всі дільники, і вони йдуть парами.
Антоній Томас

2
велике спасибі Ентоні, я зрозумів зараз: D! невеликий додаток: я думаю, що слід розглядати значення sqrt (n) окремо, тому що зараз це враховується два рази замість одного, я думаю
SummerCode

Хоча O (sqrt (n)) не надто поганий, він не є оптимальним. обчислення розкладання основного фактора можна зробити набагато швидше і достатньо для обчислення кількості дільників.
le_m

При кожній ітерації ви повинні обчислити i², чи не було б швидше порівняти i з √n (обчислюється лише один раз)?
Yukulélé

10

Це цікаве питання набагато складніше, ніж виглядає, і на нього не було відповіді. Питання можна розділити на два дуже різні питання.

1, заданий N, знайдіть список L основних факторів N

2 задано L, обчисліть кількість унікальних комбінацій

Усі відповіді, які я бачу до цих пір, відносяться до №1, і якщо не згадати, це не можна простежити у величезній кількості. Для середньо розмірних N, навіть 64-бітних чисел, це легко; для величезного N проблема факторингу може зайняти "назавжди". Від цього залежить шифрування відкритого ключа.

Питання №2 потребує більшого обговорення. Якщо L містить лише унікальні числа, це простий обчислення, використовуючи комбіновану формулу для вибору k об'єктів з n елементів. Насправді потрібно підсумовувати результати застосування формули, змінюючи k від 1 до розміру (L). Однак L, як правило, містить декілька випадків множинних простих чисел. Наприклад, L = {2,2,2,3,3,5} - це факторизація N = 360. Зараз ця проблема є досить складною!

Перезавантаження №2, задане колекцією C, що містить k елементів, таким чином, що елемент a має "дублікати, а елемент b має b" дублікати тощо. Скільки унікальних комбінацій предметів від 1 до k-1 є? Наприклад, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} кожен має відбуватися один раз і лише один раз, якщо L = {2,2 , 2,3,3,5}. Кожна така унікальна підбірка є унікальним дільником N шляхом множення елементів у підбірці.


Ось посилання на псевдо-код для проблеми, дуже схожої на 2. answer.google.com/answers/threadview/id/392914.html
mR_fr0g

3
Питання №2 має добре відоме рішення. Для факторизації {p_i, k_i} де p_iпростий множник числа з k_iкратністю - загальна кількість дільників цього числа (k_1+1)*(k_2+1)*...*(k_n+1). Я думаю, ви це вже знаєте, але я записую це на користь, якщо тут випадковий читач.
Вілл Несс

9

Відповідь на ваше запитання сильно залежить від розміру цілого числа. Методи для невеликих чисел, наприклад, менше 100 біт, а для чисел ~ 1000 біт (наприклад, що використовуються в криптографії), абсолютно різні.


6

ВІДПОВІДНО один рядок
Я дуже обережно подумав над вашим запитанням, і я намагався написати високоефективний та найефективніший фрагмент коду. Щоб надрукувати на екрані всіх дільників певного числа, нам потрібен лише один рядок коду! (використовуйте параметр -std = c99 під час компіляції через gcc)

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

Сито Аткіна - це оптимізована версія сита Ератосфена, яка дає всі прості числа до заданого цілого числа. Ви повинні мати змогу переглядати це в Google, щоб отримати докладнішу інформацію.

Після того, як у вас є цей список, просто ділити своє число на кожне просте число, щоб дізнатися, чи точний дільник (тобто, залишок - нуль).

Основними етапами обчислення дільників для числа (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 у розумний час, вона є а) не оптимальною і б) не обчислює кількість дільників заданого числа відповідно до питання ОП
le_m

І не працюватимуть для великої кількості через свою рекурсію
whackamadoodle3000

Хоча це не оптимально, а замість підрахунку факторів, воно насправді перераховує їх, простота та краса цього вражає і досить швидко. ^^
Гаурав Сінгхал

5

Після того, як у вас є основна факторизація, є спосіб знайти кількість дільників. Додайте по одному із показників на кожен окремий коефіцієнт, а потім помножте показники разом.

Наприклад: 36 Основна факторизація: 2 ^ 2 * 3 ^ 2 Дільники: 1, 2, 3, 4, 6, 9, 12, 18, 36 Кількість дільників: 9

Додайте по одному до кожного показника 2 ^ 3 * 3 ^ 3 Помножте експоненти: 3 * 3 = 9


3

Перш ніж взяти на себе рішення, подумайте, що підхід Сита може бути не гарною відповіддю в типовому випадку.

Нещодавно назад було головне питання, і я зробив тест на час - для 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 на першій ітерації тут
барфун

на жаль ні. ++ i відрізняється від i ++ (що призведе до помилки поділу на нуль)
iGbanam

Я написав вашу функцію в PHP та запустив її - ось що я отримав - i.minus.com/iKzuSXesAkpbp.png
barfoon

з якоїсь дивної причини це працювало бездоганно для мене. о добре, мій поганий. старт numberOfDivisorsі ітератор на 1; це повинно позбутися
поділки

1
Ваш алгоритм не працює для ідеальних квадратів. Наприклад, він повертає 4 для входу x = 4, тому що він рахує 2 двічі ... 1, 2, 2, 4. Відповідь має бути 3: 1,2,4
Михайло

1

Ви хочете сито Аткіна, описане тут: http://en.wikipedia.org/wiki/Sieve_of_Atkin


1
Це призведе до отримання простих ліній нижче вашого заданого номера - але немає гарантії, що ці прайми будуть дільниками? (якщо я щось не пропускаю)
Ендрю Еджкомб

Швидкий стрибок звідси, щоб знайти всі праймери <sqrt (N), які рівномірно ділять N.
SquareCog

1
Це може бути швидким стрибком, але тестування всіх прайменів <sqrt (N) все ще є поганою методикою факторингу незалежно від того, наскільки ефективно ви їх знайдете. Є багато способів покращити це.
користувач11318

Тестування праймес O (N), це пошук праймес, що є важкою частиною. Але навіть з неоптимізованим ситом ерастостена, ви все ще можете знайти всі праймери менше кількох мільйонів за секунду. Це стосується будь-якого номера 64b, і я впевнений, що тут ми не говоримо про
фактори фактори

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. Перший цікавий факт полягає в тому, що він мультиплікативний, тобто. τ (ab) = τ (a) τ (b), коли a і b не мають спільного фактора. (Доказ: кожна пара дільників a і b дає виразний дільник ab).

Тепер зауважимо, що для pa prime, τ (p ** k) = k + 1 (сили p). Таким чином, ви можете легко обчислити τ (n) з його факторизації.

Однак факторизація великої кількості може бути повільною (безпека критопрафії RSA залежить від продуктивності двох великих праймерів, які важко піддаються аналізу). Це говорить про цей оптимізований алгоритм

  1. Перевірте, чи число просте (швидке)
  2. Якщо так, поверніть 2
  3. В іншому випадку розподіліть підрахунок числа (повільно, якщо кілька великих простих факторів)
  4. Обчисліть τ (n) з факторизації

1

Далі наводиться програма С для пошуку кількості дільників заданого числа.

Складність вищевказаного алгоритму становить O (sqrt (n)).

Цей алгоритм буде правильно працювати для числа, яке є ідеальним квадратом, а також чисел, які не є ідеальним квадратом.

Зауважте, що верхнє обмеження циклу встановлено на квадратний корінь числа, щоб алгоритм був найбільш ефективним.

Зауважте, що зберігання верхнього обмеження в окремій змінній також економить час, ви не повинні викликати функцію sqrt у розділі стану циклу for, це також економить ваш час обчислення.

#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(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

@Kendall

Я перевірив ваш код і вніс деякі вдосконалення, тепер це ще швидше. Я також перевірив код @ @ هومن جاویدپور, це також швидше, ніж його код.

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

Я думаю, що це те, що ви шукаєте. Я роблю саме те, про що ви просили. Скопіюйте та вставте його в Notepad.Збережіть як * .bat.Run.Enter Number. Помножте процес на 2 і ось кількість дільників. Я зробив це за призначенням, щоб він швидше визначив дільники:

Зверніть увагу, що значення змінного нахилу 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 дільники
дон.

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

Я не знаю найбільш ефективного методу, але я би зробив наступне:

  • Створіть таблицю простих лічильників, щоб знайти всі прайми меншими або рівними квадратному кореню числа (особисто я використовував би сито Аткіна)
  • Порахуйте всі проліс, менший або рівний квадратному кореню числа, і помножте його на два. Якщо квадратний корінь числа є цілим числом, віднімайте його з змінної підрахунку.

Має працювати \ o /

Якщо вам потрібно, я можу завтра щось зашифрувати в C, щоб продемонструвати.


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