Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
 Аватар для bedvit
1209 / 260 / 22
Регистрация: 20.05.2016
Сообщений: 1,139
Записей в блоге: 22

Алгоритмы поиска всех делителей для натурального числа

27.04.2017, 19:42. Показов 2472. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Хочу поделится 2 алгоритмами, которые сегодня набросал. Диапазон задаваемых натуральных чисел до 18 446 744 073 709 551 615.
Если есть свои, более быстрые алгоритмы, интересные и необычные, прошу
Алгоритм 1.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "stdafx.h"
#include <math.h>
#include <string>
#include <vector>
#include <iostream>
#include <thread>
#include <stdio.h>
#include <time.h>
using namespace std;
 
unsigned long long n;//18446744073709551615;
unsigned long long n2;
vector<unsigned long long> a;
int threadsN; //задать количество потоков
unsigned long long k;
 
void Func(int start)
{
    unsigned long long i = start;
    for (i; i < n2; i = i + threadsN)
    {
        if (n%i == 0)
        {
            k = k + 2; 
            printf(" \n%llu \n%llu ", i, n / i);
        }
    }
    if ((i - 1)*(i - 1) == n)
    {
        k = k + 1; 
        printf("\n%llu", i - 1);
    }
}
 
int main()
{
    threadsN = thread::hardware_concurrency();
    char input[256];
    cout << "Enter the numeric for which you want to find all the divisors, followed by <Enter>:\n";
    cin >> input;
    n = strtoull(input, NULL, 0);
    unsigned int start_time = clock(); 
    n2 = (unsigned long long)sqrt(n);
    vector<thread> thr(threadsN);
    for (int i = 1; i <= threadsN; i++) thr[i - 1] = thread(Func, i);
    for (int i = 1; i <= threadsN; i++) thr[i - 1].join();
 
    unsigned int end_time = clock(); 
    unsigned int search_time = end_time - start_time; 
    printf("\n\nTime, sec (min): %f (%f) Solutions: %llu\n", search_time / 1000.0, search_time / 60000.0, k);
    system("pause");
    return 0;

Алгоритм 2
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "stdafx.h"
#include <iostream>
#include <time.h>
 
int main()
    {
        unsigned long long Ostatok;
        unsigned long long Result[1000]{ 1 };
        long ResultCount = 1;
        unsigned long long LastMn = 0;
        unsigned long long FirstMn = 2;
        long LastCount = 0;
        long LastCountTemp = 0;
        std::cout << "Enter the numeric for which you want to find all the divisors, followed by <Enter>:\n";
        std::cin >> Ostatok;
        std::cout << "Result:" << std::endl;
        unsigned int start_time = clock(); // начальное время
 
        while (Ostatok > 1) {
            for (unsigned long long Mn = FirstMn; Mn <= Ostatok; Mn++) {
                if (Ostatok%Mn == 0) {
                    LastCountTemp = ResultCount;
                    if (LastMn == Mn) {
                        for (long i = LastCount; i < LastCountTemp; i++) Result[ResultCount++] = Result[i] * Mn;
                    }
                    else
                    {
                        for (long i = 0; i < LastCountTemp; i++) Result[ResultCount++] = Result[i] * Mn;
                    }
                    Ostatok = Ostatok / Mn;
                    LastMn = Mn;
                    FirstMn = Mn;
                    LastCount = LastCountTemp;
                    break;
                }
                else
                {
                    if (Mn*Mn > Ostatok) Mn = Ostatok - 1;
                }
            }
        }
        for (long i = 0; i < ResultCount; i++)
        {
            printf("%llu\n", Result[i]);
        }
        unsigned int end_time = clock(); // конечное время
        unsigned int search_time = end_time - start_time; // искомое время
        printf("\n\nTime, sec (min): %f (%f) Solutions: %llu\n", search_time / 1000.0, search_time / 60000.0, ResultCount);
        system("pause");
        return 0;
    }

Второй явно выигрывает (коллега подкинул). Подумаю как поделить по потокам.
Вложения
Тип файла: rar С++divisors.rar (185.6 Кб, 1 просмотров)
Тип файла: rar С++divisors2.rar (124.2 Кб, 1 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.04.2017, 19:42
Ответы с готовыми решениями:

Написать рекурсивную функцию, для определения всех делителей натурального числа
помогите пожалуйста, написать рекурсивную функцию определения всех делителей натурального числа n.

Среднее арифметическое всех делителей натурального числа
Составить программу нахождения среднего арифметического значения всех делителей заданного натурального числа N(N&lt;=1000), кратных 3 и 4...

Сформировать массив из всех делителей введенного с клавиатуры натурального числа
Сформировать массив из всех делителей введенного с клавиатуры натурального числа. Сформированный массив вывести на экран.

4
 Аватар для bedvit
1209 / 260 / 22
Регистрация: 20.05.2016
Сообщений: 1,139
Записей в блоге: 22
18.05.2017, 18:31  [ТС]
Всем привет!
Тема смотрю идет в топ
Думаю я не первый, и по моему разумению не последний.
Все таки столкнувшись с данной тематикой немного погуглил, пораскинул мозгами и выкладываю решение на скромном уровне (!= Перельман Г.Я.)
Алгоритмы поиска простых(всех) делителей для натурального числа (в.ч. факторизация натурального числа)

Кратко реализация алгоритма:
1.Отказ от прямого перебора
2.Расспаралелен процесс
3.Реализована оптимизация (т. н. wheel factorization)
4.Подключена библиотека MPIR is licensed LGPL v3+.
Как подключить (Инструкции по использованию библиотек GMP и MPIR в системе Windows)
5.Прочие оптимизации:
5.1.Проверка на простое число - MPIR
5.2.Проверка на размер числа (до 2^64-1) - расчет на родном unsigned long long, быстрее чем через mpz_class библиотек MPIR.
5.3.Факторизация числа (разложение на простые делители)
Элементарно решается данным кодом поменяв строку 1 на строку 2 в коде:
C++
1
2
if (oldMn != Mn) std::cout << Mn << std::endl;//меняем на
std::cout << Mn << std::endl;
далее в проектк морф алгоритма на поиск всех делителей (не только простых) - решается не сложно.

Сборка х64
Код и .exe:
1. На unsigned long long:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <mpirxx.h>
#include <iostream>
#include <time.h>
#include <vector>
#include <thread>
 
unsigned long long Ostatok;
unsigned long long Ostatok2;
 
void Func(int start)
{
    unsigned long long Ch = (1);
    unsigned long long Mn = 30 * Ch + start;
    unsigned long long oldMn;
 
    while (Mn <= Ostatok2) {
        if (Ostatok%Mn == 0) {
            Ostatok = Ostatok / Mn;
            if (oldMn != Mn) std::cout << Mn << std::endl;
            Ostatok2 = (unsigned long long)sqrt(Ostatok);
            oldMn = Mn;
        }
        else {
            Ch++;
            Mn = 30 * Ch + start;
        }
    }
}
 
int main()
{
    std::string s;
    std::cout << "Enter the numeric for which you want to find Simple dividers, followed by <Enter>:\n";
    std::cin >> Ostatok;//s;
    std::cout << "Result:\n1" << std::endl;
    unsigned int start_time = clock(); // начальное время
    Ostatok2 = (unsigned long long)sqrt(Ostatok);
    unsigned long long Mn = (2);
    unsigned long long oldMn;
 
    while (Mn <= 30) {
        if (Ostatok%Mn == 0) {
            Ostatok = Ostatok / Mn;
            if (oldMn != Mn) std::cout << Mn << std::endl;
            Ostatok2 = (unsigned long long)sqrt(Ostatok);
            oldMn = Mn;
        }
        else { Mn++; }
    }
 
    std::vector<std::thread> thr(8);
    int arr[] = { 0,1,7,11, 13, 17, 19, 23, 29 };
    for (int i = 1; i <= 8; i++) thr[i - 1] = std::thread(Func, arr[i]);
    for (int i = 1; i <= 8; i++) thr[i - 1].join();
    if (Ostatok > 1) std::cout << Ostatok << std::endl;
    unsigned int end_time = clock(); // конечное время
    unsigned int search_time = end_time - start_time; // искомое время
    printf("\nTime, sec (min): %f (%f) \n", search_time / 1000.0, search_time / 60000.0);
    system("pause");
    return 0;
}

Через mpz_class библиотек MPIR:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <mpirxx.h>
#include <iostream>
#include <time.h>
#include <vector>
#include <thread>
 
unsigned long long Ostatok;
unsigned long long Ostatok2;
mpz_class mpz_Ostatok;
mpz_class mpz_Ostatok2;
 
void Func(int start)
{
    unsigned long long Ch=(1);
    unsigned long long Mn = 30 * Ch + start;
    unsigned long long oldMn;
 
    while (Mn <= Ostatok2) {
        if (Ostatok%Mn == 0) {
            Ostatok = Ostatok / Mn;
            if (oldMn != Mn) std::cout << Mn << std::endl;
            Ostatok2 = (unsigned long long)sqrt(Ostatok);
            oldMn = Mn;
        }
        else{
            Ch++;
            Mn = 30 * Ch + start;
        }
    }
}
void Func2(int start)
{
    mpz_class Ch = (1);
    mpz_class Mn = 30 * Ch + start;
    mpz_class oldMn;
 
    while (Mn <= mpz_Ostatok2) {
        if (mpz_Ostatok%Mn == 0) {
            mpz_Ostatok = mpz_Ostatok / Mn;
            if (oldMn != Mn) std::cout << Mn << std::endl;
            mpz_Ostatok2 = sqrt(mpz_Ostatok);
            oldMn = Mn;
        }
        else {
            Ch++;
            Mn = 30 * Ch + start;
        }
    }
}
int main()
{
    bool mpz_Start;
    mpz_class oldMn;
    std::string s;
    std::cout << "Enter the numeric for which you want to find Simple dividers, followed by <Enter>:\n";
    std::cin >> s;//Ostatok;//s;
    std::cout << "Result:\n1" << std::endl;
    unsigned int start_time = clock(); // начальное время
    mpz_Ostatok = s;
    if (mpz_probab_prime_p(mpz_Ostatok.get_mpz_t(), 100) == 0) {
 
        std::vector<std::thread> thr(8);
        int arr[] = { 0,1,7,11, 13, 17, 19, 23, 29 };
 
        if (mpz_Ostatok > 18446744073709551615) {
            mpz_Ostatok2 = sqrt(mpz_Ostatok);
            mpz_class Mn = (2);
            mpz_class oldMn;
            while (Mn <= 30) {
                if (mpz_Ostatok%Mn == 0) {
                    mpz_Ostatok = mpz_Ostatok / Mn;
                    if (oldMn != Mn) std::cout << Mn << std::endl;
                    mpz_Ostatok2 =sqrt(mpz_Ostatok);
                    oldMn = Mn;
                }
                else { Mn++; }
            }
            for (int i = 1; i <= 8; i++) thr[i - 1] = std::thread(Func2, arr[i]);
            for (int i = 1; i <= 8; i++) thr[i - 1].join();
            if (mpz_Ostatok > 1) std::cout << mpz_Ostatok << std::endl;
        }
        else {
            Ostatok = mpz_Ostatok.get_ui();
            Ostatok2 = (unsigned long long)sqrt(Ostatok);
            unsigned long long Mn = (2);
            unsigned long long oldMn;
            while (Mn <= 30) {
                if (Ostatok%Mn == 0) {
                    Ostatok = Ostatok / Mn;
                    if (oldMn != Mn) std::cout << Mn << std::endl;
                    Ostatok2 = (unsigned long long)sqrt(Ostatok);
                    oldMn = Mn;
                }
                else { Mn++; }
            }
            for (int i = 1; i <= 8; i++) thr[i - 1] = std::thread(Func, arr[i]);
            for (int i = 1; i <= 8; i++) thr[i - 1].join();
            if (Ostatok > 1) std::cout << Ostatok << std::endl;
        }
    }
    else { std::cout << s << std::endl; }
    unsigned int end_time = clock(); // конечное время
    unsigned int search_time = end_time - start_time; // искомое время
    printf("\nTime, sec (min): %f (%f) \n", search_time / 1000.0, search_time / 60000.0);
    system("pause");
    return 0;
}


Здоровый конструктивизм приветствуется!
Жду ваших оценок, где можно допилить, в каком бы направлении пошли бы Вы.
В блоге подробно расписана тема.
Вложения
Тип файла: rar C++Simple_number_dividers.rar (287.8 Кб, 2 просмотров)
0
 Аватар для bedvit
1209 / 260 / 22
Регистрация: 20.05.2016
Сообщений: 1,139
Записей в блоге: 22
18.05.2017, 21:26  [ТС]
Корректная ссылка на блог.
0
 Аватар для bedvit
1209 / 260 / 22
Регистрация: 20.05.2016
Сообщений: 1,139
Записей в блоге: 22
23.05.2017, 17:15  [ТС]
Кому интересно добавил функционал к вешевыложенному решению.
ФУНКЦИОНАЛ:
1.Факторизация числа
2.Поиск простых делителей числа
3.Поиск всех делителей числа
К примеру поиск решения для 25-35 десятичных знаков- от долей секунды и выше (сильно зависит от количества мелких простых делителей, общего количества простых делителей и других особенностей разложения числа).
Решение.
0
 Аватар для SerVal
37 / 36 / 9
Регистрация: 16.04.2015
Сообщений: 283
01.05.2022, 01:32
C++
1
2
3
4
5
6
7
8
9
10
H:\aProjects\BigIntCuda\x64\Release>BigIntCuda.exe -factorial 1000000
 
AMD Ryzen 5 3500 6-Core Processor
 
Calculating 1000000!
 big integer :  8 ... 0
 number of decimal digits = 5565709
 number of segments       = 618413
 
time : 9.847 sec.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.05.2022, 01:32
Помогаю со студенческими работами здесь

Составьте программу вывода на экран всех делителей натурального числа N
Добрый вечер всем, помогите пожалуйста решить задачу.Составьте программу вывода на экран всех делителей натурального числа N

Для заданного натурального числа n найти сумму всех его делителей
Для заданного натурального числа n найти сумму всех его делителей

Написать процедуру поиска всех делителей заданного числа и их суммы
нужна помощь в решении задач в Visual C++. без решения не сдать экзамен. HELP!! задачи простые, но язык совсем не знаю. 1)написать...

Составить программу, которая вычисляет количество S всех делителей и сумму Y всех делителей натурального числа N
1. Дано натуральное число N (N&lt;104). Составить программу, которая вычисляет количество S всех делителей и сумму Y всех делителей...

Нахождение для заданного натурального числа н всех делителей
Помогите, пожалуйста решить задачи. Знаю, что не сложные, но я в паскале полный тормоз, а решения нужно сдать. 1. Составить программу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! в-строка - входное арифметическое выражение в инфиксной(обычной). . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru