Created readme.md
This commit is contained in:
220
README.md
Normal file
220
README.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# Алгоритмы решения прикладных задач, 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 <vector>
|
||||
#include <map>
|
||||
|
||||
#include "sieveoferatosthenes.cpp"
|
||||
|
||||
// Функция для факторизации числа (метод простого перебора)
|
||||
std::map<int, int> factorize(int number) {
|
||||
std::map<int, int> factors;
|
||||
std::vector<int> 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 <vector>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
|
||||
#include "sieveoferatosthenes.cpp"
|
||||
|
||||
// Функция для факторизации числа методом Ферма
|
||||
std::map<int, int> fermatFactorize(int number) {
|
||||
std::map<int, int> factors;
|
||||
|
||||
// Проверка на простоту
|
||||
std::vector<int> primes = sieveOfEratosthenes(static_cast<int>(sqrt(number)) + 1);
|
||||
for (int prime : primes) {
|
||||
if (prime * prime > number) break;
|
||||
while (number % prime == 0) {
|
||||
factors[prime]++;
|
||||
number /= prime;
|
||||
}
|
||||
}
|
||||
|
||||
// Если число больше 1, применяем метод Ферма
|
||||
if (number > 1) {
|
||||
int a = static_cast<int>(ceil(sqrt(number)));
|
||||
int b2 = a * a - number;
|
||||
int b = static_cast<int>(sqrt(b2));
|
||||
|
||||
while (b * b != b2) {
|
||||
a++;
|
||||
b2 = a * a - number;
|
||||
b = static_cast<int>(sqrt(b2));
|
||||
}
|
||||
|
||||
int factor1 = a - b;
|
||||
int factor2 = a + b;
|
||||
|
||||
// Добавляем найденные множители
|
||||
factors[factor1]++;
|
||||
factors[factor2]++;
|
||||
}
|
||||
|
||||
return factors;
|
||||
}
|
||||
```
|
||||
|
||||
### Задание 4
|
||||
|
||||
Написать программу для проверки на простоту числа Мерсенна с использование теста Люка-Лемера. С клавиатуры вводится номер числа Мерсенна
|
||||
|
||||
```cpp
|
||||
#include <cmath>
|
||||
|
||||
// Функция для проверки, является ли число простым
|
||||
bool isPrime(int p) {
|
||||
if (p <= 1) return false;
|
||||
if (p <= 3) return true;
|
||||
if (p % 2 == 0 || p % 3 == 0) return false;
|
||||
for (int i = 5; i * i <= p; i += 6) {
|
||||
if (p % i == 0 || p % (i + 2) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Тест Люка-Лемера для проверки простоты числа Мерсенна
|
||||
bool lucasLehmerTest(int p) {
|
||||
if (p == 2) return true; // M_2 = 3, простое число
|
||||
|
||||
// Вычисляем M_p = 2^p - 1
|
||||
long long M_p = (1LL << p) - 1; // 1LL << p эквивалентно 2^p
|
||||
|
||||
// Начальное значение s
|
||||
long long s = 4;
|
||||
|
||||
// Выполняем тест
|
||||
for (int 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 <vector>
|
||||
|
||||
std::vector<int> vonNeumannSequence(unsigned long int n) {
|
||||
|
||||
std::vector<int> 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 <iostream>
|
||||
|
||||
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 << " ";
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user