Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 11.10.2023
Сообщений: 13
1

Поменять местами два числа в массиве, которые имеют наибольшее количество делителей

22.10.2023, 16:46. Показов 581. Ответов 8

Author24 — интернет-сервис помощи студентам
Дан массив из 12 натуральных целых чисел. Поменять местами два числа, которые имеют наибольшее количество делителей.
Значения в массив вводятся с клавиатуры
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
22.10.2023, 16:46
Ответы с готовыми решениями:

Определить количество цифр в цифровой записи данного числа, которые имеют наибольшее значение
Дано натуральное число N. Определить количество цифр в цифровой записи данного числа, которые...

Определить количество цифр в цифровой записи данного числа, которые имеют наибольшее значение
Дано натуральное число N. Определить количество цифр в цифровой записи данного числа, которые имеют...

Определить количество цифр в цифровой записи данного числа, которые имеют наибольшее значение.
Дано натуральное число N. Определить количество цифр в цифровой записи данного числа, которые имеют...

Определить количество цифр в цифровой записи данного числа, которые имеют наибольшее значение
Дано натуральное число N. Определить количество цифр в цифровой записи данного числа, которые имеют...

Как поменять местами в двумерном массиве два числа?
using System; using System.Collections.Generic; using System.Linq; using System.Text; using...

8
Модератор
Эксперт CЭксперт С++
 Аватар для Volga_
5202 / 2919 / 1509
Регистрация: 14.12.2018
Сообщений: 5,261
Записей в блоге: 1
22.10.2023, 17:04 2
Alexey_Kursk, можно использовать следующую функцию для нахождения количества делителей числа:
C++
1
2
3
4
5
6
7
int f(int n) 
{
    int res = 1;
    for (int i = 2; i <= n / 2 + 1; i++)
        if (n % i == 0) res++;
    return res + 1;
}
1
 Аватар для ram876
758 / 455 / 213
Регистрация: 19.12.2016
Сообщений: 1,815
22.10.2023, 18:03 3
Ноль тоже можно считать натуральным числом и у него делитель любое число кроме нуля. Это как то надо учитывать?
0
0 / 0 / 0
Регистрация: 11.10.2023
Сообщений: 13
22.10.2023, 18:15  [ТС] 4
0 учитывать не нужно
0
 Аватар для igorrr37
2862 / 2010 / 988
Регистрация: 21.12.2010
Сообщений: 3,716
Записей в блоге: 15
23.10.2023, 06:46 5
Пусть N - число, кол-во делителей которого надо найти. Решетом создаём массив всех простых от 2 до sqrt(N). С помощью этого массива раскладываем N на произведение простых делителей. Находим кол-во всех сочетаний найденных простых делителей.
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
#include <iostream>
#include <unordered_map>
#include <cmath>
#include <numeric>
#include <algorithm>
#include <list>
#include <forward_list>
#include <vector>
#include <climits>
#include <random>
#include <ctime>
 
int main()
{
    int num = 2e9; // число, делители которого ищем
 
    std::vector<int> vPrimes((int)std::sqrt(INT_MAX));
    std::iota(vPrimes.begin(), vPrimes.end(), 2);
 
    // решето Эратосфена
    int ind{};
    for (int i = 2; i < vPrimes.size(); i += 2) // для 2
    {
        vPrimes[i] = 0;
    }
    for (int i = 1; i < vPrimes.size() && ind < vPrimes.size(); ++i) // для > 2
    {
        int p = vPrimes[i];
        if (!p)
            continue;
        ind = p * p - 2;
        int step = 2 * p;
        for (int j = ind; j < vPrimes.size(); j += step)
        {
            vPrimes[j] = 0;
        }
    }
 
    std::mt19937 eng{(unsigned)time(nullptr)};
    std::uniform_int_distribution uid{(int)2, (int)2e9};
 
    while (true)
    {
        num = uid(eng);
        int tmpNum = num;
        std::unordered_map<int, int> ump;
        for (int i = 0; tmpNum != 1 && i < vPrimes.size(); ++i)
        {
            if (vPrimes[i] == 0)
                continue;
            while (tmpNum % vPrimes[i] == 0)
            {
                tmpNum /= vPrimes[i];
                ++ump[vPrimes[i]];
            }
        }
        if (tmpNum != 1)
            ++ump[tmpNum];
 
        // кол-во всех сочетаний простых делителей
        int cnt{ 1 };
        for (auto const& [k, v] : ump)
        {
            cnt *= v + 1;
        }
        std::cout << cnt << "\n";
 
        // наивный алгоритм для проверки
        int sqrtNum = std::sqrt(num);
        int cntNaiv = (sqrtNum * sqrtNum == num ? 1 : 2);
        for (int i = 2; i <= sqrtNum; ++i)
        {
            if (num % i == 0)
            {
                cntNaiv += 2;
            }
        }
        std::cout << cntNaiv << "\n";
        
        if (cnt != cntNaiv)
        {
            std::cerr << "Error: " << num << "\n";
            break;
        }
    }
}
Добавлено через 8 минут
Volga_, можно ускорить если идти до корня а не до n/2
C++
1
2
3
4
5
6
7
8
9
10
int sqrtNum = std::sqrt(num);
int cntNaiv = (sqrtNum * sqrtNum == num ? 1 : 2);
for (int i = 2; i <= sqrtNum; ++i)
{
    if (num % i == 0)
    {
        cntNaiv += 2;
    }
}
std::cout << cntNaiv << "\n";
1
 Аватар для igorrr37
2862 / 2010 / 988
Регистрация: 21.12.2010
Сообщений: 3,716
Записей в блоге: 15
23.10.2023, 08:06 6
Но при большом количестве запросов решето быстрей чем даже корень из N
Миниатюры
Поменять местами два числа в массиве, которые имеют наибольшее количество делителей  
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12812 / 6684 / 1800
Регистрация: 18.10.2014
Сообщений: 16,935
23.10.2023, 08:50 7
Цитата Сообщение от igorrr37 Посмотреть сообщение
Но при большом количестве запросов решето быстрей чем даже корень из N
Ключевой момент здесь - нахождение количества делителей через факторизацию, а не через перебор всевозможных делителей. А уже делать ли факторизацию с решетом или без... не так важно.

Более того, если оптимизировать поиск делителей вот так Получить все простые делители числа, это наверное, даст чуть ли не ту же самую практическую эффективность, чем заранее построенное решето.

Добавлено через 33 минуты
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
unsigned num_of_divisors(unsigned long long v)
{
  unsigned nod = 1;
 
  unsigned long long r = std::sqrt(v);
  
  for (unsigned d : { 2, 3, 5, 7 })
    if (v % d == 0)
    {
      unsigned m = 2;
      for (v /= d; v % d == 0; v /= d, ++m);
      nod *= m;
    }
 
  for (unsigned long long d = 11; d <= r;)
  {
    for (unsigned a : 
           { 
             2, 4, 2, 4, 6, 2, 6, 4, 
             2, 4, 6, 6, 2, 6, 4, 2, 
             6, 4, 6, 8, 4, 2, 4, 2, 
             4, 8, 6, 4, 6, 2, 4, 6, 
             2, 6, 6, 4, 2, 4, 6, 2, 
             6, 4, 2, 4, 2, 10, 2, 10
           })
    {
      if (v % d == 0)
      {
        unsigned m = 2;
        for (v /= d; v % d == 0; v /= d, ++m);
        nod *= m;
      }
      
      d += a;
    }
  }
    
  if (v != 1)
    nod *= 2;
 
  return nod;
}
1
 Аватар для igorrr37
2862 / 2010 / 988
Регистрация: 21.12.2010
Сообщений: 3,716
Записей в блоге: 15
23.10.2023, 10:22 8
TheCalligrapher, потестил. Твой алгос лучше наивного, но до решета не дотягивает. Вот времена и тестовая прога. Может напутал чего
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <iostream>
#include <unordered_map>
#include <cmath>
#include <numeric>
#include <algorithm>
#include <list>
#include <forward_list>
#include <vector>
#include <climits>
#include <random>
#include <ctime>
#include <chrono>
 
int main()
{
    int num = 2e9; // число, делители которого ищем
 
    std::vector<int> vPrimes((int)std::sqrt(INT_MAX));
    std::iota(vPrimes.begin(), vPrimes.end(), 2);
 
    // построение решета Эратосфена
    int ind{};
    for (int i = 2; i < vPrimes.size(); i += 2) // для 2
    {
        vPrimes[i] = 0;
    }
    for (int i = 1; i < vPrimes.size() && ind < vPrimes.size(); ++i) // для > 2
    {
        int p = vPrimes[i];
        if (!p)
            continue;
        ind = p * p - 2;
        int step = 2 * p;
        for (int j = ind; j < vPrimes.size(); j += step)
        {
            vPrimes[j] = 0;
        }
    }
    vPrimes.erase(std::remove(vPrimes.begin(), vPrimes.end(), 0), vPrimes.end());
 
    std::mt19937 eng{(unsigned)time(nullptr)};
    std::uniform_int_distribution uid{(int)2, (int)2e9};
    std::unordered_map<int, int> ump;
    int testLim = 1e4; // кол-во запросов
    while (true)
    {
        num = uid(eng);
        int cntErat{}, cntNaiv{}, cntCallig{};
 
        // алгоритм решето тест
        auto time1 = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < testLim; ++i)
        {
            int tmpNum = num;
            for (auto it = vPrimes.begin(); tmpNum >= *it * *it; ++it)
            {
                while (tmpNum % *it == 0)
                {
                    tmpNum /= *it;
                    ++ump[*it];
                }
            }
            if (tmpNum != 1)
                ++ump[tmpNum];
 
            // кол-во всех сочетаний простых делителей
            cntErat = 1;
            for (auto const& [k, v] : ump)
            {
                cntErat *= v + 1;
            }
            //std::cout << cntErat << "\n";
            ump.clear();
        }
        auto time2 = std::chrono::high_resolution_clock::now();
 
        // алгоритм TheCalligrapher тест
        for (int i = 0; i < testLim; ++i)
        {
            int tmpNum = num;
            cntCallig = 1;
            unsigned long long r = std::sqrt(tmpNum);
 
            for (unsigned d : { 2, 3, 5, 7 })
                if (tmpNum % d == 0)
                {
                    unsigned m = 2;
                    for (tmpNum /= d; tmpNum % d == 0; tmpNum /= d, ++m);
                    cntCallig *= m;
                }
 
            for (unsigned long long d = 11; d <= r;)
            {
                for (unsigned a :
                {
                    2, 4, 2, 4, 6, 2, 6, 4,
                        2, 4, 6, 6, 2, 6, 4, 2,
                        6, 4, 6, 8, 4, 2, 4, 2,
                        4, 8, 6, 4, 6, 2, 4, 6,
                        2, 6, 6, 4, 2, 4, 6, 2,
                        6, 4, 2, 4, 2, 10, 2, 10
                })
                {
                    if (tmpNum % d == 0)
                    {
                        unsigned m = 2;
                        for (tmpNum /= d; tmpNum % d == 0; tmpNum /= d, ++m);
                        cntCallig *= m;
                    }
                    d += a;
                }
            }
 
            if (tmpNum != 1)
                cntCallig *= 2;
        }
        auto time3 = std::chrono::high_resolution_clock::now();
 
        // наивный алгоритм тест
        for (int i = 0; i < testLim; ++i)
        {
            int sqrtNum = std::sqrt(num);
            cntNaiv = (sqrtNum * sqrtNum == num ? 1 : 2);
            for (int i = 2; i <= sqrtNum; ++i)
            {
                if (num % i == 0)
                {
                    cntNaiv += 2;
                }
            }
            //std::cout << cntNaiv << "\n";
        }
        auto time4 = std::chrono::high_resolution_clock::now();
 
        std::cout 
            << std::chrono::duration_cast<std::chrono::milliseconds>(time2 - time1).count() << "  "
            << std::chrono::duration_cast<std::chrono::milliseconds>(time3 - time2).count() << "  "
            << std::chrono::duration_cast<std::chrono::milliseconds>(time4 - time3).count() << "\n";
        
        if (cntErat != cntNaiv || cntCallig != cntNaiv)
        {
            std::cerr << "Error: " << num << "\n";
            break;
        }
    }
}
Миниатюры
Поменять местами два числа в массиве, которые имеют наибольшее количество делителей  
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12812 / 6684 / 1800
Регистрация: 18.10.2014
Сообщений: 16,935
24.10.2023, 05:43 9
Цитата Сообщение от igorrr37 Посмотреть сообщение
Твой алгос лучше наивного, но до решета не дотягивает.
Я сделал глупость в своей реализации. Вычислять r = std::sqrt(v); заранее и потом проверять до этого r - это, конечно же, чушь полнейшая.

Правильно:

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
unsigned num_of_divisors(unsigned long long v)
{
  unsigned nod = 1;
 
  for (unsigned d : { 2, 3, 5, 7 })
    if (v % d == 0)
    {
      unsigned m = 2;
      for (v /= d; v % d == 0; v /= d, ++m);
      nod *= m;
    }
 
  for (unsigned long long d = 11; d * d <= v;)
  {
    for (unsigned a : 
           { 
             2, 4, 2, 4, 6, 2, 6, 4, 
             2, 4, 6, 6, 2, 6, 4, 2, 
             6, 4, 6, 8, 4, 2, 4, 2, 
             4, 8, 6, 4, 6, 2, 4, 6, 
             2, 6, 6, 4, 2, 4, 6, 2, 
             6, 4, 2, 4, 2, 10, 2, 10
           })
    {
      if (v % d == 0)
      {
        unsigned m = 2;
        for (v /= d; v % d == 0; v /= d, ++m);
        nod *= m;
      }
      
      d += a;
    }
  }
    
  if (v != 1)
    nod *= 2;
 
  return nod;
}
Такой вариант, конечно, на больших числах тоже будет проигрывать заранее приготовленному решету, но не так ужасно, как получилось в ваших тестах выше.
1
24.10.2023, 05:43
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.10.2023, 05:43
Помогаю со студенческими работами здесь

Найдите количество чисел от 1 до n, которые имеют четное количество делителей
Вам дано целое число n. Найдите количество чисел от 1 до n, которые имеют четное количество...

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

Найти в массиве два числа, являющимися перевертышами друг друга и поменять их местами.
дано массив с элементами а1, а2, ... {a}_{n}. найдите две целых чисел что бы они поменяли местами....

Найти такие натуральные числа M1 и N1, которые не имеют общих делителей
Дано натуральные числа M и N. Найти такие натуральные числа M1 и N1, которые не имеют общих...

В промежутке от 1 до 1001 найти все числа которые имеют 5 делителей
1)Объясните почему delete не работает 2)Как правильно сделать эту задачу. мне кажется я её делаю...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Элементы алгоритмизации
hw_wired 28.01.2025
Основы алгоритмизации В современном мире алгоритмы играют фундаментальную роль в развитии информационных технологий и программирования. Понимание основ алгоритмизации является ключевым элементом в. . .
Человек и информация
hw_wired 28.01.2025
Введение: роль информации в познании мира В современном мире информация играет фундаментальную роль в процессе познания окружающей действительности. Она представляет собой совокупность сведений об. . .
Компьютер и информация
hw_wired 28.01.2025
Эволюция вычислительных машин История развития вычислительной техники начинается задолго до появления первых электронных устройств. Человечество всегда стремилось упростить процесс вычислений и. . .
Информационные технологии
hw_wired 28.01.2025
Введение в современные технологии работы с информацией В современном мире информационные технологии стали неотъемлемой частью практически всех сфер человеческой деятельности. Они существенно. . .
Информация вокруг нас
hw_wired 28.01.2025
Основные понятия информации В современном мире понятие информации является фундаментальным и охватывает практически все сферы человеческой деятельности. Информация представляет собой совокупность. . .
Компьютер для начинающих
hw_wired 28.01.2025
Введение в мир компьютерных технологий В современном мире информация стала одним из важнейших ресурсов человечества, определяющим развитие общества и технологий. Наша жизнь неразрывно связана с. . .
[golang] 189. Rotate Array
alhaos 28.01.2025
Повороты рукоятки, целочисленный слайс нужно сдвинуть на целое положительное число. Мне очень нравится решение на GO / / https:/ / leetcode. com/ studyplan/ top-interview-150/ package topInterview . . .
КуМир: решение задач на матрицы
bytestream 28.01.2025
КуМир представляет собой среду для обучения программированию, которая включает в себя мощные инструменты для работы с матрицами. Матрица в программировании - это двумерный массив, состоящий из. . .
КуМир: решение задач на строки
bytestream 28.01.2025
В системе программирования КуМир работа со строковыми данными является одним из важнейших аспектов создания программ. Строки представляют собой последовательности символов, заключенные в кавычки,. . .
КуМир: решение геометрических задач
bytestream 28.01.2025
Программирование геометрических задач в среде КуМир становится всё более актуальным в обучении школьников и студентов. КуМир — это разработанная в России обучающая программная среда, предназначенная. . .
КуМир, исполнитель Водолей: Задачи и решения
bytestream 28.01.2025
КуМир — это образовательная среда для обучения программированию. Она предлагает пользователям разнообразные инструменты для разработки и отладки программ, что особенно ценно для студентов и. . .
КуМир, исполнитель Чертежник: Решение задач
bytestream 28.01.2025
КуМир (Комплект Учебных МИРов) представляет собой образовательную среду для обучения основам программирования и алгоритмизации. Исполнитель Чертежник работает на координатной плоскости, где может. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru