Как найти нод код

Задача:

Найти наименьшее общее кратное для всех элементов массива — минимальное число, которое делится на все элементы массива без остатка. Также, найти НОД всех элементов массива.

Решение:

Вот тут приведены алгоритмы расчета НОК и НОД для двух чисел. Ясно, что наиболее эффективный алгоритм расчета НОК двух чисел — это произведение чисел поделить на их НОД. По содержимому статьи ясно что НОК(а1, а2, а3, ... аN) равен НОК(НОК(НОК(А1, А2), А3)..., АN). Таким образом, для расчета НОК массива чисел надо многократно расчитывать НОД двух чисел, реализация этой функции на С++ взята тут.

Реализация на Си (функции чуть-чуть изменены, так как добавлена самописная функция swap):

#include <stdio.h>
#include <stdlib.h>

void read_array(int n, int** values) {
    for (int i = 0; i < n; ++i) {
        printf("values[%d] = ", i);
        scanf("%d", &((*values)[i]));
    }
}

void print_array(int n, int* values) {
    for (int i = 0; i < n; ++i) {
        printf("values[%d] = %dn", i, values[i]);
    }
}

void swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int gcd(int a, int b) {
    if (a < b) {
        swap(&a, &b);
    }
    while (a % b != 0) {
        a = a % b;
        swap(&a, &b);
    }
    return b;
}

int gcd_n(int n, int* values) {
    if (n == 0)
        return -1;
    if (n == 1)
        return values[0];
    int gcd_value = gcd(values[0], values[1]);
    for (int i = 2; i < n; ++i) {
        gcd_value = gcd(gcd_value, values[i]);
    }
    return gcd_value;
}

int lcm(int a, int b) {
    return (a*b)/gcd(a, b);
}

int lcm_n(int n, int* values) {
    if (n == 0)
        return -1;
    if (n == 1)
        return values[0];
    int lcm_value = lcm(values[0], values[1]);
    for (int i = 2; i < n; ++i) {
        lcm_value = lcm(lcm_value, values[i]);
    }
    return lcm_value;
}

int main() {
    int n;
    int *values;
    
    printf("n: ");
    scanf("%d", &n);
    
    values = malloc(sizeof(int) * n);
    
    read_array(n, &values);
    
    printf("lcm: %d", lcm_n(n, values));
    
    free(values);
    return 0;
}

Алгоритм Евклида

Для начала разберемся, что это и как это работает. Алгоритм Евклида позволяет найти нам наибольший общий делитель чисел. Как это работает:
Пусть a = 18, b = 30.
Цикл: a!=0 and b!=0
Если a > b, то a = a % b, если меньше, то b = b % a, таким образом мы сначала находим остаток деления, а потом повторяем действия. У нас a < b, значит, ищем остаток деления b % a (30 % 18) = 12, присваиваем b = 12, повторяем цикл но теперь у нас уже a > b(b = 12)
значит выполняем a % b (18 % 12) = 6? снова переходим к циклу, теперь снова b > a, значит выполняем b % a (30 % 6), остаток от деления 0, на этом мы прекращаем наш цикл и узнаем, что наибольший общий делитель 18 и 30 = 6. и выводим a + b (b = 0, a = 6).

Python

#!/usr/bin/env python
a = 18
b = 30
 
while a!=0 and b!=0:
    if a > b:
        a = a % b
    else:
        b = b % a
 
print (a+b)

Perl:

 sub nod
 {
 return  $_[0] != 0  ?  nod ( ( $_[1] % $_[0] ), $_[0] )  :  $_[1];
 }

C:

 int gcd(int a, int b) {
   int c;
   while (b) {
      c = a % b;
      a = b;
      b = c;        
   }
   return abs(a);
 }

Pascal:

  function nod( a, b: longint): longint; 
  begin
   while (a <> 0) and (b <> 0) do
     if a >= b then 
       a:= a mod b 
     else 
       b:= b mod a;
   nod:= a + b;
  end;

Java:

public class GCD {
    public static int gcd(int a,int b) {
        while (b !=0) {
            int tmp = a%b;
            a = b;
            b = tmp;
        }
        return a;
    }
}

C#:

int gcd(int a, int b)
{
    while (b != 0)
        b = a % (a = b);
    return a;
}

19 / 19 / 4

Регистрация: 18.02.2011

Сообщений: 292

1

Нахождение НОД

14.10.2011, 21:50. Показов 51144. Ответов 13


Студворк — интернет-сервис помощи студентам

Здравствуйте, мне надо найти НОД чисел. Как это реализовать на языке C++ ?



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

14.10.2011, 21:50

13

2554 / 1319 / 178

Регистрация: 09.05.2011

Сообщений: 3,086

Записей в блоге: 1

14.10.2011, 21:53

2



0



19 / 19 / 4

Регистрация: 18.02.2011

Сообщений: 292

14.10.2011, 22:13

 [ТС]

3

я пробую, но у меня ничего не выводит на экран!



0



447 / 210 / 21

Регистрация: 07.10.2011

Сообщений: 462

14.10.2011, 22:25

4

PaZL, ну тогда код в студию. Или мы должны угадать, почему оно не работает?



1



Эксперт С++

4265 / 2239 / 203

Регистрация: 26.08.2011

Сообщений: 3,802

Записей в блоге: 5

15.10.2011, 09:38

5



0



156185

19 / 19 / 4

Регистрация: 18.02.2011

Сообщений: 292

15.10.2011, 12:45

 [ТС]

6

C++
1
2
3
4
5
6
7
8
9
long Nod(long a, long b)
{
    while (a && b)
        if (a >= b)
           a %= b;
        else
           b %= a;
    return a | b;
}

мне пишет

Код

c:mingwbin..libgccmingw324.5.2......libmingw32.a(main.o):main.c|| undefined reference to `WinMain@16'|



0



447 / 210 / 21

Регистрация: 07.10.2011

Сообщений: 462

15.10.2011, 13:20

7

PaZL, это мы и так поняли, полный код нужен и другие сведения. Где ваша функция main()? Какой у вас компилятор и тип проекта

Если б была Visual Studio, то на такую ошибку я б сказала, что у вас проект не того типа создан



0



Higher

1953 / 1219 / 120

Регистрация: 02.05.2010

Сообщений: 2,925

Записей в блоге: 2

15.10.2011, 13:23

8

Цитата
Сообщение от aeshes
Посмотреть сообщение

PaZL, это мы и так поняли, полный код нужен и другие сведения. Где ваша функция main()? Какой у вас компилятор и тип проекта

Если б была Visual Studio, то на такую ошибку я б сказала, что у вас проект не того типа создан

Есть сильное подозрение, что это и есть полный код =)



0



19 / 19 / 4

Регистрация: 18.02.2011

Сообщений: 292

15.10.2011, 13:26

 [ТС]

9

aeshes, у меня компилятор MinGW, IDE: CodeBlocks. Я новичок в C++, помогите составить полный код, чтобы выводила результат.



0



aeshes

447 / 210 / 21

Регистрация: 07.10.2011

Сообщений: 462

15.10.2011, 13:26

10

Не по теме:

diagon, я тоже подозревала, но хочется верить в хорошее в людях))

PaZL, в приведенных примерах есть только реализация метода поиска НОД. Чтобы посмотреть, как он работает, вам надо помимо этого создать еще функцию int main(), подключить нужные библиотеки, ввести 2 числа и вызвать для них функцию

примерно так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
 
long Nod(long a, long b)
{
    while (a && b)
        if (a >= b)
           a %= b;
        else
           b %= a;
    return a | b;
}
 
int main()
{
   int a,b;
   std::cout<<"a=";
   std::cin>>a;
   std::cout<<"b=";
   std::cin>>b;
   std::cout<<Nod(a,b);
}



4



В вечном поиске…

275 / 235 / 30

Регистрация: 05.04.2011

Сообщений: 645

15.10.2011, 13:28

11

PaZL, а книжку открыть не вариант?



0



19 / 19 / 4

Регистрация: 18.02.2011

Сообщений: 292

15.10.2011, 13:50

 [ТС]

12

aeshes, спасибо все получилось!



0



0 / 0 / 0

Регистрация: 27.07.2016

Сообщений: 1

08.01.2017, 18:54

13

Ребят, объясните чайнику как работает return a | b; Я понимаю, что оно возвращает не равное 0 значение, но что это за выражение такое? Что это вообще за |. Впервые вижу.



0



Падаван С++

447 / 261 / 89

Регистрация: 11.11.2014

Сообщений: 916

08.01.2017, 19:40

14

Fozek, битовое или, почитайте про битовые операции



1



Алгоритм Евклида – нахождение наибольшего общего делителя

Алгоритм Евклида – это алгоритм нахождения наибольшего общего делителя (НОД) пары целых чисел.

Наибольший общий делитель (НОД) – это число, которое делит без остатка два числа и делится само без остатка на любой другой делитель данных двух чисел. Проще говоря, это самое большое число, на которое можно без остатка разделить два числа, для которых ищется НОД.

Решение задачи на языке программирования Python

Алгоритм нахождения НОД делением

  1. Большее число делим на меньшее.
  2. Если делится без остатка, то меньшее число и есть НОД (следует выйти из цикла).
  3. Если есть остаток, то большее число заменяем на остаток от деления.
  4. Переходим к пункту 1.

Пример:
Найти НОД для 30 и 18.
30 / 18 = 1 (остаток 12)
18 / 12 = 1 (остаток 6)
12 / 6 = 2 (остаток 0)
Конец: НОД – это делитель 6.
НОД (30, 18) = 6

a = int(input())
b = int(input())
 
while a != 0 and b != 0:
    if a > b:
        a = a % b
    else:
        b = b % a
 
print(a + b)

В цикле в переменную a или b записывается остаток от деления. Цикл завершается, когда хотя бы одна из переменных равна нулю. Это значит, что другая содержит НОД. Однако какая именно, мы не знаем. Поэтому для определения НОД находим сумму этих переменных. Поскольку в одной из переменных ноль, он не оказывает влияние на результат.

Если условием завершения цикла является равенство хотя бы одной из переменных нулю (a == 0 or b == 0), то условием продолжения его работы является обратное этому условие – обе переменные должны иметь отличные от нуля значения (a != 0 and b != 0).

Блок-схема алгоритма Евклида

Для того, чтобы вышеприведенная программа могла обрабатывать отрицательные числа, в логическом выражении при if должны сравниваться модули значений переменных: if abs(a) > abs(b):. Иначе большим числом может оказаться меньшее по модулю. В этом случае интерпретатор Питона в качестве остатка от деления выдает вещественное число. В результате это приводит к зацикливанию, так как низвести переменные до нуля становится как минимум маловероятным.

Алгоритм нахождения НОД вычитанием

  1. Из большего числа вычитаем меньшее.
  2. Если получается 0, значит, числа равны друг другу и являются НОД (следует выйти из цикла).
  3. Если результат вычитания не равен 0, то большее число заменяем на результат вычитания.
  4. Переходим к пункту 1.

Пример:
Найти НОД для 30 и 18.
30 – 18 = 12
18 – 12 = 6
12 – 6 = 6
6 – 6 = 0
Конец: НОД – это уменьшаемое или вычитаемое.
НОД (30, 18) = 6

a = int(input())
b = int(input())
 
while a != b:
    if a > b:
        a = a - b
    else:
        b = b - a
 
print(a)

Функция, вычисляющая НОД

def gcd(m, n):
    while m != n:
        if m > n:
            m = m - n
        else:
            n = n - m
    return n
 
 
a = int(input())
b = int(input())
 
print(gcd(a, b))

Функция gcd модуля math

В модуле math языка программирования Python есть функция gcd, вычисляющая наибольший общий делитель двух чисел.

>>> import math
>>> math.gcd(30, 18)
6

Больше задач в PDF

 

Наибольшим общим делителем (НОД) для двух целых чисел m и n называется наибольшее число, на которое делятся числа m и n. Наибольший общий делитель существует и однозначно определён, если хотя бы одно из чисел m или n не равно нулю.

Алгоритм был придуман Евклидом в Древней Греции более 2000 лет назад и основан на следующем правиле.

Для любых целых чисел x, y > 0 выполняется равенство

НОД (x, y) = НОД (x % y, y)

 
Любое число, которое делит оба числа x и y, делит также и x — y, поэтому

НОД (x, y) ≤ НОД (x — y, y).

 
Аналогично, любое число, которое делит оба числа x − y и y, делит также и их сумму x, поэтому

НОД (x, y) ≥ НОД (x — y, y).

 

Требуемое равенство получается последовательным вычитанием y из x.

Идея алгоритма отыскания наибольшего общего делителя заключается в том, чтобы отнимать от большего меньшее, пока числа не станут равны. Полученное число и является наибольшим общим делителем.

Например, необходимо определить наибольший общий делитель чисел 50 и 20.

  • находим 50-20=30. Из трех чисел 50, 20, 30 отбрасываем наибольшее.
  • находим 30-20=10. Из трех чисел 30, 20, 10 отбрасываем наибольшее.
  • находим 20-10 = 10. Из трех чисел 20, 10, 10 отбрасываем наибольшее.
  • 10=10, значит это число является наибольшим общим делителем исходных.
 

Реализацию указанного алгоритма удобно произвести с использованием рекурсивной процедуры.

 
Реализация на С++

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

#include <iostream>
using namespace std;
// Функция нахождения НОД
int NOD(int n1, int n2)
{
  int div;
  if (n1 == n2)   // если числа равны, НОД найден
    return n1;
  int d = n1 – n2; // Находим разность чисел
  if (d < 0)       // если разность отрицательная,
  {
    d = -d;     // меняем знак
    div = NOD(n1, d); // вызываем функцию NOD() для двух наименьших чисел
  }
  else      // если разность n1-n2 положительная
  {
    div = NOD(n2, d); // вызываем функцию NOD() для двух наименьших чисел
  }
  return div;
}
int main() 
{
  int n1, n2;
  cout << “n1=”;
  cin >> n1;
  cout << “n2=”;
  cin >> n2;
  cout << NOD(n1, n2);
  cin.get(); cin.get(); return 0;
}

Результат выполнения
Наибольший общий делитель

Назад: Алгоритмизация

Добавить комментарий