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

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

Запись от Тамика размещена 21.07.2014 в 13:43
Показов 5114 Комментарии 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 вне форума
 
Новые блоги и статьи
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
Диалоги с ИИ
zorxor 23.05.2026
Насколько я понимаю - Вы - Искусственный Интеллект. Это так? Да, всё верно. Я — искусственный интеллект. Я представляю собой большую языковую модель, созданную для помощи в самых разных задачах. . . .
Модель здравосохранения 14. Собираем всю модель вместе.
anaschu 22.05.2026
Модель собрана. В будущих постах на видео я покажу, как она работает. В этом посте запускаем её, проверяем результаты и разбираем что можно с ней делать дальше. Перед запуском проверяем. . .
Модель здравоохранения 13. Добавление самой системы здравоохранения.
anaschu 22.05.2026
В предыдущем посте мы настроили болезни. Теперь добавим события, которые управляют здоровьем всего коллектива, а также настроим рабочий график и расчёт финансов. В Main создаём четыре события. . . .
Модель здравоохранения 12. добавление болезней через ресурпул, как аварии
anaschu 22.05.2026
Болезни — это ключевая часть нашей модели. Нам нужно, чтобы работник периодически уходил на больничный, его задание при этом зависало, а после выздоровления работа возобновлялась. Реализуем это двумя. . .
Модель здравоохранения 11. Создаём классы Задание и Работник
anaschu 22.05.2026
В AnyLogic каждая заявка и каждый ресурс — это объект определённого класса. Нам нужно создать два класса: Задание (заявка) и Работник (ресурс). Класс Задание В дереве проекта нажимаем правой. . .
Модель здравоохранения 10. Новая модель, смотрим, как добавлять логические блоки, и что писать внутри
anaschu 22.05.2026
Открываем AnyLogic, создаём новый проект. В дереве проекта появляется класс Main — это главный агент, в котором будет жить вся наша логика. Палитра блоков Слева находится палитра. Нас интересует. . .
модель ЗдравоСохранения 9. Новая модель, разбираемся, как ее создавать
anaschu 22.05.2026
В этой серии постов мы построим модель небольшого рабочего коллектива. Сотрудники получают задания, выполняют их, иногда болеют — и мы хотим посчитать, сколько это стоит компании. Метод. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru