Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/47: Рейтинг темы: голосов - 47, средняя оценка - 4.87
16 / 14 / 7
Регистрация: 04.11.2011
Сообщений: 137
1

Алгоритм проверки числа на "совершенность"

09.07.2013, 17:31. Показов 8989. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Приветствую всех!

Прошу помочь со следующей задачей:

"Натуральное число называется совершенным, если оно равно сумме всех своих делителей, за исключением себя самого. Число 6 – совершенное, так как 6 = 1+2+3. Число 8 – не совершенное, так как 8 ≠ 1+2+4.Дано натуральное число n. Получить все совершенные числа, меньшие n."

Задачу я решил (код ниже), но работает программа слишком медленно. Пожалуйста помогите оптимизировать код, нужно чтобы программа требовала, как можно меньше памяти и работала быстрее.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
using namespace std;
 
bool perfect(int x)
{
   int sum=0;
   for (int i=1; i<x; i++)
      if (x%i==0) sum+=i;
   if (x==sum) return 1;
   return 0;
}
 
int main()
{
   int x;
   cin >> x;
   for (int i=1; i<=x; i++)
      if (perfect(i)) cout << i << endl;
   return 0;
}
Ссылки на литературу по сабжу приветствуются.

Заранее всем благодарен))
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.07.2013, 17:31
Ответы с готовыми решениями:

Проверка числа на совершенность
Задача: использовать функцию, которая определяет, является ли введённое число совершенным или нет +...

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

Алгоритм проверки делимости числа на 7
Предлагаю алгоритм проверки делимости числа на 7. Описание алгоритма и примеры его применения...

Быстрый алгоритм проверки числа на простоту
Я уже пробовал перебор делителей числа. public bool IsPrime(BigInteger number) { for (int...

Нужен алгоритм проверки большого числа на простоту
Нужен быстрый код, который проверит число типа BigInteger на простоту (простое это число или нет)....

42
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
09.07.2013, 20:04 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Toshkarik Посмотреть сообщение
Thinker, так скорей всего Ваш код и будет быстрее, так как операция деления довольно дорогая.
Спасибо, что понимаете в том алгоритме по сути не используется свойство:
если a делитель n, то и n/a тоже делитель, там еще более крутые моменты (мультипликативные функции), поэтому быстро работает
P.S. а то бы не выставлял бы тот алгоритм. интересно было поработать с мульт.функциями, после чего пришла идея такого алгоритма.
0
Модератор
Эксперт по электронике
8909 / 6678 / 918
Регистрация: 14.02.2011
Сообщений: 23,524
09.07.2013, 20:18 22
Цитата Сообщение от Kukurudza Посмотреть сообщение
Toshkarik на самом деле на сегодняшний момент операция деления такая же по стоимости как и умножение.
не совсем уверен i5 нет проверить не могу
но до него div достаточно дорогая операция была
Цитата Сообщение от Kukurudza Посмотреть сообщение
как она реадизована я не в курсе
очень часто деление заменяется на умножение и сдвиг
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
09.07.2013, 20:23 23
Kukurudza, я что то разве говорил об умножении? Я сравнивал с битовыми операциями.
0
16 / 14 / 7
Регистрация: 04.11.2011
Сообщений: 137
10.07.2013, 09:36  [ТС] 24
ValeryS, спасибо за замечания)) Сразу как-то и не подумал над х/2.
Чуть-чуть причесал код:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
bool perfect(unsigned int x)
{
   unsigned int sum=0;
   for (int i=1; i<=x/2; i++)
      if (x%i==0) sum+=i;
   return x==sum;
}
 
int main()
{
   unsigned int x;
   std::cin >> x;
   for (unsigned int i=4; i<=x; i++)
      if (perfect(i)) std::cout << i << std::endl;
   return 0;
}

Kukurudza, благодарю за вики, появились кое какие мысли) Использование последовательности чисел Мерсенне способ весьма годный на практике, но когда речь идёт об алгоритмизации думаю не совсем уместен.

Цитата Сообщение от Kukurudza Посмотреть сообщение
реализованный алгоритм имеет нотацию O(n*n)
Это оценка скорости выполнения или количества операций алгоритма? Можно подробнее?

Thinker, Ваш алгоритм нахождения делителей числа действительно очень быстро работает. Еще не разобрался как он работает...

Вообщем по алгоритму проверки числа на совершенность пока идей больше нет, а вот как сократить количество итераций проверки самих чисел меньше заданного n (по условию) есть. Заинтересовало сл. св-во совершенных чисел в вики:
"Все чётные совершенные числа в двоичной записи содержат сначала p единиц, за которыми следует p—1 нулей (следствие из их общего представления)."

Таким образом можно было бы проверять все числа от 4 до n сначала на удовлетворение этому условию (операция, как я полагаю, менее затратная, если не ошибаюсь) и только проходящие по нему проверять на совершенность.
0
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
10.07.2013, 09:39 25
Цитата Сообщение от Naudiz Посмотреть сообщение
Thinker, Ваш алгоритм нахождения делителей числа действительно очень быстро работает. Еще не разобрался как он работает...
Спасибо, всякую фигню бы не стал выставлять на показ Возможно, оптимизирую его как-нибудь.
0
106 / 87 / 13
Регистрация: 29.08.2012
Сообщений: 539
10.07.2013, 10:02 26
Цитата Сообщение от Naudiz Посмотреть сообщение
Это оценка скорости выполнения или количества операций алгоритма? Можно подробнее?
ей богу, у меня иногда складывается мнение что только у меня гугл разбанен:
http://ru.wikipedia.org/wiki/%... 0%B8%D1%8F
а вообще это у вас академическая задача или какая-то практическая? решили нобеля получить поди?
0
2 / 2 / 1
Регистрация: 17.04.2012
Сообщений: 22
10.07.2013, 10:17 27
если интересно разобраться с О( ) и с другими её друзьями - "Алгоритмы построения и анализ" авторы: Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн)
1
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
10.07.2013, 12:31 28
Naudiz,
Быстрый поиск совершенных чисел
0
16 / 14 / 7
Регистрация: 04.11.2011
Сообщений: 137
12.07.2013, 20:50  [ТС] 29
Thinker, благодарю, то что нужно. Можно вопрос по Вашему коду?

C++
1
const unsigned long long N = 5000000000000000000llu; //3я строка
Что значит "llu"?

Эта запись в дальнейшем фигурирует в выражениях в main
0
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
12.07.2013, 20:53 30
Цитата Сообщение от Naudiz Посмотреть сообщение

Что значит "llu"?

Эта запись в дальнейшем фигурирует в выражениях в main
везде llu замените на ull это константа типа unsigned long long
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
12.07.2013, 20:57 31
Самый быстрый поиск совершенных чисел. Берем гугл. Сбиваем "OEIS совершенные числа". Находим эту страницу - http://oeis.org/A000396 Копируем все числа в константы (хоть в строковые). Организуем поиск по константам. Радуемся сложности O(1)
0
16 / 14 / 7
Регистрация: 04.11.2011
Сообщений: 137
12.07.2013, 21:03  [ТС] 32
Thinker, не понял. В Вашем коде именно llu и он компилируется и работает))

Добавлено через 45 секунд
Dani, не смешно.
0
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
12.07.2013, 21:04 33
Цитата Сообщение от Naudiz Посмотреть сообщение
Thinker, не понял. В Вашем коде именно llu и он компилируется и работает))
тогда оставьте. ull нужно для работы с огромными типизированными константами, в противном случае число 50...0 просто урежется.
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
12.07.2013, 21:07 34
Цитата Сообщение от Naudiz Посмотреть сообщение
Dani, не смешно.
Никто шутить и не собирался. Работает быстро и правильно.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <algorithm>
 
int main()
{
    const std::string arr[] = {"6","28","496","8128","33550336","8589869056","137438691328","2305843008139952128","2658455991569831744654692615953842176",
        "191561942608236107294793378084303638130997321548169216"}; //совершенные числа
    const int len = 10; //количество совершенных чисел
    std::string inp_number;
    std::cin >> inp_number;
    std::cout << ( std::find(arr, arr+len, inp_number) != arr+len ? "It is perfect number" : "It is not perfect number") << std::endl;
    return 0;
}
0
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
12.07.2013, 21:12 35
Dani, программа дает иллюзию, что что ты сам их находишь
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
12.07.2013, 21:13 36
Thinker, Зато 10 чисел найдет В отличии от других программ.
0
16 / 14 / 7
Регистрация: 04.11.2011
Сообщений: 137
12.07.2013, 21:15  [ТС] 37
Dani, речь идёт именно об "алгоритме проверки числа на совершенность", а не о выводе совершенных чисел на экран.

Thinker, а что происходит в 57 строке? Заранее извиняюсь, мне еще не по зубам такой код(
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
12.07.2013, 21:16 38
Naudiz, здесь и проверяется число на совершенность, как ты мог заметить.
0
Эксперт С++
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
12.07.2013, 21:19 39
Dani, программа дает иллюзию, что если вдруг ОЗУ позволит хранить очень большие числа, то с ее помощью можно найти еще несколько дополнительных чисел, не вошедших в ТОП10

Добавлено через 2 минуты
Цитата Сообщение от Naudiz Посмотреть сообщение
Thinker, а что происходит в 57 строке?
это просто. с помощью побитовых операций вычисляем значение
https://www.cyberforum.ru/cgi-bin/latex.cgi?2^{i-1}(2^i-1)
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
12.07.2013, 21:23 40
Цитата Сообщение от Thinker Посмотреть сообщение
программа дает иллюзию
но она ведь правильно проверяет число на совершенность. что и требовалось
Цитата Сообщение от Naudiz Посмотреть сообщение
нужно чтобы программа требовала, как можно меньше памяти и работала быстрее.
Что ТС просил - все условия выполняются.
Если нужно научиться находить совершенные числа или в учебных целях - то с твоим кодом никто не конкурирует, но пусть большие числа считает, например, этот сайт http://oddperfect.org/
Да и BigInt юзать как-то неохота в связи с затратами и повышением сложности кода.
1
12.07.2013, 21:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.07.2013, 21:23
Помогаю со студенческими работами здесь

Алгоритм выделения разрядов числа и проверки, есть ли среди них нечетная цифра
Задание. Дано трехзначное число. Составить алгоритм выделения его разрядов и проверки, есть ли...

Составить алгоритм проверки гипотезы Гольдбаха о представлении каждого чётного числа в виде суммы двух простых
Составить алгоритм проверки гипотезы Гольдбаха о представлении каждого чётного числа n(n&gt;2) в виде...

Дано четырехзначное число. Составить алгоритм выделения его разрядов и проверки, составляют ли цифры числа упорядоченную последовательность.
Дано четырехзначное число. Составить алгоритм выделения его разрядов и проверки,...

Написать код программы проверки целого числа на симметрию , проверки строки на симметрию символов
Код на C++ Помогите пожалуйста!

нахождение среднего арифметического всего массива и проверка на совершенность
Помогите пожалуйста с задачей: дан массив- 20 элементов, необходимо найти среднее арифметическое...

Алгоритм проверки
Всем доброго времени суток! Есть один код, это как бы шашки. Задача программы определить какие...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru