2024-10-26 09:57:38 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:57:38 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00
2024-10-26 09:11:25 +03:00

Алгоритмы решения прикладных задач, 1-й семестр, 2-я практика

Практика затрагивает алгоритмы нахождения наибольшего общего делителя (метод деления, метод вычитания), алгоритмы поиска простых чисел (решето Эратосфена, решето Сундарама, тест Люка-Лемера), алгоритмы факторизации чисел (алгоритм Ферма), алгоритмы генерации псевдослучайных чисел (числа фон Неймана).

Задания

Задание 1

Написать программу для поиска наибольшего общего делителя (числа вводятся с клавиатуры после запуска программы): Нечетные варианты: наибольший делитель трех чисел методом деления (для поиска остатка отделения в языке C++ используется операция %) Четные варианты: наибольший общий делитель четырех чисел метолом вычитания

// Функция для нахождения НОД двух чисел (метод деления)
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

Написать программу для факторизации заданного с клавиатуры числа методом простого перебора (указать простые множители и их кратность). Для анализа числа на простоту использовать решето Эратосфена

#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

Написать программу для факторизации заданного с клавиатуры нечетного числа методом Ферма (указать простые множители и их кратность). Для анализа числа на простоту использовать решето Эратосфена

#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

Написать программу для проверки на простоту числа Мерсенна с использование теста Люка-Лемера. С клавиатуры вводится номер числа Мерсенна

#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 пятизначных чисел фон Неймана

#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

Написать программу для поиска простых чисел по алгоритму «Решето Сундарама»

#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 << " ";
  }
}
Description
Алгоритмы решения прикладных задач, 1-й семестр, 2-я практика
Readme 60 KiB
Languages
C++ 100%