Форум программистов, компьютерный форум, киберфорум
Тамика
Войти
Регистрация
Восстановить пароль

Решение задач ProjectEuler №3 и № 4.

Запись от Тамика размещена 21.07.2014 в 13:43
Показов 5215 Комментарии 18
Метки c++

Задача №3.
Простые делители числа 13195 это 5, 7, 13 и 29. Какой максимальный простой делитель у числа 600851475143?

Решение.
Как бы я ни старалась упростить код, выполнение всё равно занимает много времени. Тут уже ничего не поделаешь, потому как входное число большое. Но если у кого есть советы по оптимизации - буду благодарна.
З.Ы. Решето Эратосфена тут не подойдет, потому как создать вектор с сайзом 600851475143 жестоко по отношению к памяти.

Потому решила эту задачу более прямо, хотя решение занимает почти полторы секунды.
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <cstdlib>
#include <chrono>
#include <vector>
#include <cassert>
 
bool is_prime(unsigned long long num)
{
        for (unsigned long long  i = 2; i < num; ++i)
                if(num % i == 0) return false;
 
        return true;
}
 
unsigned long long  solve(unsigned long long  below_value)
{
        int p = 2;
        for (int i = 2; i < below_value; ++i)
                if (below_value % i == 0 && is_prime(below_value / i)) return below_value/i;
}
 
int main()
{
        assert(solve(10) == 5);
        auto  now = std::chrono::high_resolution_clock::now();
        auto answer = solve(600851475143);
        auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - now);
        std::cout << "Answer = " << answer << "\n";
        std::cout << "Time : " << elapsed.count() << "ns.\n";
        return 0;
}


Задача №4.
Палиндромные числа читаются одинаково как слева направо, так и наоборот. Самый большой палиндром, который можно получить умножением двух двузначных чисел - 9009 = 91*99.
А теперь найдите самый большой палиндром, который можно получить умножением трёхзначных чисел.


Решение.
Кликните здесь для просмотра всего текста
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 <iostream>
#include <chrono>
#include <cassert>
#include <algorithm>
 
bool is_palindrom(long int num)
{
        int b = 0;
        int a = num;
        while(num != 0)
        {
            b = b * 10 + num % 10;
            num /= 10;
        }
        if (a == b)
            return true;
 
        return false;
}
 
int solve(int count_of_digits)
{
        std::cout << count_of_digits << std::endl;
        int start = 0, end = 0;
 
        if (count_of_digits == 2) { start = 10; end = 99; }
 
        if (count_of_digits == 3) { start = 100; end = 999; }
 
        std::cout << start << std::endl;
        std::cout << end << std::endl;
 
        int mod = 0;
        int max = 0;
        for (int i = start; i <= end; ++i)
        {
                for(int j = start; j <= end; ++j)
                {
                    mod = i*j;
                    if (is_palindrom(mod))
                    {
                        if (mod > max) max = mod;
                    }
 
                }
        }
 
        return max;
}
 
int main()
{
        auto result = solve(2);
        assert(result == 9009);
        auto  now = std::chrono::high_resolution_clock::now();
        auto answer = solve(3);
        auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - now);
        std::cout << "Answer = " << answer << "\n";
        std::cout << "Time : " << elapsed.count() << "ns.\n";
        return 0;
}
Метки c++
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 18
Комментарии
  1. Старый комментарий
    Аватар для soon
    Я стараюсь решать подобные задачки на каком-нибудь функциональном языке. Вот, к примеру, вторая на Haskell

    Haskell
    1
    2
    3
    4
    5
    6
    7
    8
    
    Prelude> let isPalindrome x = s == reverse s where s = show x
    Prelude> let numbers = [100..999]
    Prelude> let products = numbers >>= (\x -> map (x*) numbers)
    Prelude> let palindromes = filter isPalindrome products
    Prelude> :set +s
    Prelude> maximum palindromes
    906609
    (0.55 secs, 575070128 bytes)
    Довольно наглядно и терпимо по времени
    Запись от soon размещена 21.07.2014 в 22:47 soon вне форума
  2. Старый комментарий
    0.55 secs
    0,048535662 сек.
    Вроде тоже терпимо.
    А сколько Ваш Хаскель возьмёт за третью задачу?
    Запись от Тамика размещена 22.07.2014 в 09:39 Тамика вне форума
  3. Старый комментарий
    Вот вам решение 3 задачи намного быстрее(но на c#)
    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
    
    static bool is_Prime(long value)//не для всех. Те, что кратны 2 пройдут проверку, но они сюда не попадают
            { 
                for (long i = 3; i < value/2; i += 2)
                    if (value % i == 0)
                        return false;
                return true;
     
            }
            static long solve(long value)
            {
                long num = 3;
                long answer = 2;//минимально возможный простой делитель у числа
                while (value % 2 == 0)
                    value /= 2;
                while (value != 1)
                    for (long i = num; i <= value; i += 2)
                        if (value % i == 0)
                        {
                            value /= i;
                            if (is_Prime(i)) answer = i;
                            num = i;
                            break;
                        }
                return answer;
            }
            static void Main(string[] args)
            {
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                long value = 600851475143;
                sw.Start();
                long answer = solve(value);
                sw.Stop();
                Console.WriteLine(answer);
                Console.WriteLine(sw.Elapsed);
            }
    Запись от rutelun размещена 22.07.2014 в 12:07 rutelun вне форума
  4. Старый комментарий
    Ну зачем мне шарп? Я на плюсах пишу. Вот на них и интересует более быстрое решение.
    Но спасибо за предложенный вариант.
    Запись от Тамика размещена 22.07.2014 в 12:45 Тамика вне форума
  5. Старый комментарий
    Вот вам решение 3 задачи намного быстрее(но на c#)
    Сколько?
    Запись от Тамика размещена 22.07.2014 в 12:46 Тамика вне форума
  6. Старый комментарий
    На них почти так же будет. Время 00:00:00.0011786
    Запись от rutelun размещена 22.07.2014 в 13:12 rutelun вне форума
  7. Старый комментарий
    на плюсах вроде бы так будет
    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
    
    #include <iostream>
    #include <cstdlib>
    #include <chrono>
    #include <vector>
    #include <cassert>
     
    bool is_prime(unsigned long long value)
    {
        for (unsigned long long i = 3; i < value / 2; i += 2)
            if (value % i == 0)
                return false;
        return true;
    }
     
    unsigned long long  solve(unsigned long long  value)
    {
        unsigned long long num = 3;
        unsigned long long answer = 2;//минимально возможный простой делитель у числа
        while (value % 2 == 0)
            value /= 2;
        while (value != 1)
            for (long i = num; i <= value; i += 2)
                if (value % i == 0)
                {
            value /= i;
            if (is_prime(i)) answer = i;
            num = i;
            break;
                }
        return answer;
    }
     
    int main()
    {
        assert(solve(10) == 5);
        auto  now = std::chrono::high_resolution_clock::now();
        auto answer = solve(600851475143);
        auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - now);
        std::cout << "Answer = " << answer << "\n";
        std::cout << "Time : " << elapsed.count() << "ns.\n";
        return 0;
    }
    Запись от rutelun размещена 22.07.2014 в 13:19 rutelun вне форума
  8. Старый комментарий
    Ваш код на g++ выдаёт такое.
    Answer = 6857
    Time : 127760ns.

    Грац! Это и правда быстрее.
    Благодарю.
    Запись от Тамика размещена 22.07.2014 в 13:26 Тамика вне форума
  9. Старый комментарий
    Аватар для soon
    Можно еще ускорить, если заменить
    C++
    1
    
    for (unsigned long long i = 3; i < value / 2; i += 2)
    на
    C++
    1
    
    for (unsigned long long i = 3; i * i <= value; i += 2)
    Старая:

    Code
    1
    2
    
    Answer = 6857
    Time : 48763ns.
    Новая:

    Code
    1
    2
    
    Answer = 6857
    Time : 29487ns.
    А сколько Ваш Хаскель возьмёт за третью задачу?
    С третьей сложнее. Наивное решение хоть и выглядит прилично, но, боюсь, так и не закончит вычисления. Всякие уловки, вроде вероятностных тестов дико выглядят, но не приносят вменяемого результата. Так что я пока в процессе
    Запись от soon размещена 24.07.2014 в 08:28 soon вне форума
  10. Старый комментарий
    Аватар для bormant
    Решето Эратосфена тут не подойдет
    Если оно не хранится, это еще не значит, что не используется ;-)

    Хозяйке на заметку: в задаче №3 функция is_prime() лишняя совсем: если на очередной кандидат в простые поделилось без остатка -- этот кандидат не может быть составным числом (все простые, что меньше этого текущего кандидата, уже исключены из разложения на предыдущих шагах).

    C++
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    unsigned long long solve(unsigned long long value)
    {
        unsigned long long answer = 0;
        while (value % 2 == 0) {
            value /= 2; answer = 2;
        }
        for (unsigned long i = 3; i * i <= value; i += 2) {
            while (value % i == 0) {
                value /= i; answer = i;
            }
        }
        return answer > value ? answer : value;
    }
    А если вспомнить, что шаг между кандидатами в простые в исследуемом диапазоне чередуется как 2, 4:
    C++
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    unsigned long long solve(unsigned long long value)
    {
        unsigned long long answer = 0;
        while (value % 2 == 0) {
            value /= 2; answer = 2;
        }
        while (value % 3 == 0) {
            value /= 3; answer = 3;
        }
        for (unsigned long i = 5, delta = 2; i * i <= value; i += delta, delta ^= 6) {
            while (value % i == 0) {
                value /= i; answer = i;
            }
        }
        return answer > value ? answer : value;
    }
    Стоит ли выносить answer=...; из цикла или с этим и оптимизатор сам справится предлагается выяснить самостоятельно.

    Речь про
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    unsigned long long solve(unsigned long long value)
    {
        unsigned long long answer = 0;
        if (!(value % 2)) {
            answer = 2; do value /= 2; while (!(value % 2));
        }
        if (!(value % 3)) {
            answer = 3; do value /= 3; while (!(value % 3));
        }
        for (unsigned long i = 5, delta = 2; i * i <= value; i += delta, delta ^= 6) {
            if (!(value % i)) {
                answer = i; do value /= i; while (!(value % i)); 
            }
        }
        return answer > value ? answer : value;
    }
    Запись от bormant размещена 13.12.2018 в 15:52 bormant вне форума
  11. Старый комментарий
    Аватар для Байт
    З.Ы. Решето Эратосфена тут не подойдет, потому как создать вектор с сайзом 600851475143 жестоко по отношению к памяти.
    Ну, во-первых такой сайз и не нужен. достаточно условия size*size > 600851475143
    Во-вторых можно предложить хорошую упаковку решета. В каждой тридцатке (не считая первой) есть всего 8 чисел, подозрительных на простоту. То есть информацию о простоте 30 чисел можно уложить в 8 битов, и - какая удача! - ровно в 1 байт
    Не знаю, помогут ли эти соображения справиться с вашим монстром, но кой-какую экономию памяти они дают.
    Экзерсисы на эту тему от вашего покорного слуги где-то уже были на форуме. Если интересно, попробую поискать.
    Для вашего конкретного числа потребуется память порядка 250000 байт, что уже вполне реально.
    Конечно, это не панацея, потребность в памяти сокращается только в разы, но все-таки...
    Запись от Байт размещена 14.12.2018 в 13:46 Байт вне форума
  12. Старый комментарий
    Запись от bedvit размещена 14.12.2018 в 15:10 bedvit вне форума
  13. Старый комментарий
    Аватар для bedvit
    Можно что-то побольше (рендомное число - 27 знаков):
    Enter the numeric: 131456489789465133213248979
    Result:
    1
    3
    7
    109
    227
    337
    107246330293516327

    Time, sec (min): 1.924000 (0.032067) Solutions: 7
    Запись от bedvit размещена 14.12.2018 в 15:14 bedvit вне форума
  14. Старый комментарий
    Аватар для bedvit
    Конечно, все зависит от алгоритма и числа.
    К примеру такое число, см. ниже из 35 знаков раскладывается на простые множители за 0.022 секунды, потому что у него много делителей, быстро убывает остаток неразложенного числа, отсекая заведомо ненужные расчеты.
    Enter the numeric: 32145698745623154896521456325789541
    Result:
    1
    3
    43
    89
    421
    1471
    3139
    3827
    18559
    279371
    72587646
    Time, sec (min): 0.022000 (0.000367) Solutions: 11

    А такое см. ниже.(40 знаков) уже за 165.8 секунды, потому как делителей меньше, само число больше, меньше этапов отсечения лишних расчетов, больше времени на перебор.
    Enter the numeric: 1236541236987456214532145698745632554159
    Result:
    1
    7
    61
    11969
    468883099
    27339429457
    18874212319751

    Time, sec (min): 165.806000 (2.763433) Solutions: 7
    Запись от bedvit размещена 14.12.2018 в 18:02 bedvit вне форума
  15. Старый комментарий
    Все просты делители числа 600851475143:
    Ого, спасибо большое за комментарии!

    Вот как раз пришла к Вашему способу, потому на видео моего канала уже решено быстро и просто Как раз Вашим методом
    Запись от Тамика размещена 18.12.2018 в 13:15 Тамика вне форума
  16. Старый комментарий
    Экзерсисы на эту тему от вашего покорного слуги где-то уже были на форуме. Если интересно, попробую поискать.
    Рада Вас снова видеть у себя в блоге! Заходите почаще

    Конечно интересно
    Запись от Тамика размещена 18.12.2018 в 16:07 Тамика вне форума
  17. Старый комментарий
    Аватар для Байт
    Конечно интересно
    Искать долго не пришлось. Ибо уважаемый bedvit дал ссылку на свой блог, где это обсуждалась https://www.cyberforum.ru/blog... g4754.html
    Но хочу заметить, что его исследования на эту тему и глубже, и интереснее, чем все что может предложить ваш покорный слуга.
    Запись от Байт размещена 18.12.2018 в 22:08 Байт вне форума
  18. Старый комментарий
    Аватар для bedvit
    Байт, благодарю за оценку и содержательные комментарии в моем блоге.
    Тамика, конечно есть и более быстрые алгоритмы, к примеру Общий метод решета числового поля
    Запись от bedvit размещена 20.12.2018 в 21:53 bedvit вне форума
 
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru