# Алгоритмы решения прикладных задач, 1-й семестр, 2-я практика Практика затрагивает алгоритмы нахождения наибольшего общего делителя (метод деления, метод вычитания), алгоритмы поиска простых чисел (решето Эратосфена, решето Сундарама, тест Люка-Лемера), алгоритмы факторизации чисел (алгоритм Ферма), алгоритмы генерации псевдослучайных чисел (числа фон Неймана). ## Задания ### Задание 1 Написать программу для поиска наибольшего общего делителя (числа вводятся с клавиатуры после запуска программы): Нечетные варианты: наибольший делитель трех чисел методом деления (для поиска остатка отделения в языке C++ используется операция %) Четные варианты: наибольший общий делитель четырех чисел метолом вычитания ```cpp // Функция для нахождения НОД двух чисел (метод деления) int gcdDivision(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } // Функция для нахождения НОД трех чисел int gcdOfThreeNumbers(int x, int y, int z) { return gcdDivision(gcdDivision(x, y), z); } // Функция для нахождения НОД двух чисел методом вычитания int gcdSubtraction(int a, int b) { while (a != b) { if (a > b) { a -= b; } else { b -= a; } } return a; // или b, так как a == b } // Функция для нахождения НОД четырех чисел int gcdOfFourNumbers(int w, int x, int y, int z) { return gcdSubtraction(gcdSubtraction(gcdSubtraction(w, x), y), z); } ``` ### Задание 2 Написать программу для факторизации заданного с клавиатуры числа методом простого перебора (указать простые множители и их кратность). Для анализа числа на простоту использовать [решето Эратосфена](src/sieveoferatosthenes.cpp) ```cpp #include #include #include "sieveoferatosthenes.cpp" // Функция для факторизации числа (метод простого перебора) std::map factorize(int number) { std::map factors; std::vector primes = sieveOfEratosthenes(number); for (int prime : primes) { if (prime * prime > number) break; while (number % prime == 0) { factors[prime]++; number /= prime; } } if (number > 1) { factors[number]++; } return factors; } ``` ### Задание 3 Написать программу для факторизации заданного с клавиатуры нечетного числа методом Ферма (указать простые множители и их кратность). Для анализа числа на простоту использовать решето Эратосфена ```cpp #include #include bool isPerfectSquare(int num) { int s = static_cast(sqrt(num)); return (s * s == num); } int main() { long long n; std::cout << "Введите n (произведение двух простых чисел p и q): "; std::cin >> n; long long m = static_cast(sqrt(n)); long long x = 1; while (true) { long long q = (m + x) * (m + x) - n; if (isPerfectSquare(q)) { long long k = static_cast(sqrt(q)); long long p = m + x - k; long long q_value = m + x + k; std::cout << "Найдены p и q: p = " << p << ", q = " << q_value << std::endl; break; } x++; } return 0; } ``` ### Задание 4 Написать программу для проверки на простоту числа Мерсенна с использование теста Люка-Лемера. С клавиатуры вводится номер числа Мерсенна ```cpp #include #include // Тест Люка-Лемера для проверки простоты числа Мерсенна bool lucasLehmerTest(long long p) { if (p == 2) return true; // M_2 = 3, простое число // Вычисляем M_p = 2^p - 1 long long M_p = pow(2, p) - 1; std::cout << M_p << std::endl; // Начальное значение s long long s = 4; // Выполняем тест for (long long i = 3; i <= p; ++i) { s = (s * s - 2) % M_p; // s = s^2 - 2 } // Если s % M_p == 0, то M_p простое return s == 0; } ``` ### Задание 5 Написать программу для генерации последовательности из 10 пятизначных чисел фон Неймана ```cpp #include std::vector vonNeumannSequence(unsigned long int n) { std::vector sequence; for (int i = 0; i < 10; i++) { retry: n = n*n; n = (n / 100)%100000; if (n < 10000 || n >= 1000000) { goto retry; } sequence.push_back(n); } return sequence; } ``` ### Задание 6 Написать программу для поиска простых чисел по алгоритму «Решето Сундарама» ```cpp #include void Sundaram(bool A[], int N) { int i, j; for (i = 1; i <= N; i++) A[i] = true; i = 1; j = 1; while ((2 * i * j + i + j) <= N) { while (j <= (N - i) / (2 * i + 1)) { A[2 * i * j + i + j] = false; j++; } i++; j = i; } for (i = 1; i <= N; i++) { if (A[i]) std::cout << 2 * i + 1 << " "; } } ```