Как найти наибольший общий делитель массива

Задача:

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

Решение:

Вот тут приведены алгоритмы расчета НОК и НОД для двух чисел. Ясно, что наиболее эффективный алгоритм расчета НОК двух чисел — это произведение чисел поделить на их НОД. По содержимому статьи ясно что НОК(а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;
}

0 / 0 / 0

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

Сообщений: 17

1

Найти наибольший общий делитель всех элементов массива

20.01.2012, 04:15. Показов 9034. Ответов 11


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

Такая задача: Найти наибольший общий делитель всех элементов массива (на который они все делятся без остатка).



0



41 / 41 / 36

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

Сообщений: 151

20.01.2012, 08:46

2

Достаточно одного исходника написанного на любом С++ компилляторе. Подожди немного, сейчас накидаю программку.



0



diagon

Higher

1953 / 1219 / 120

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

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

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

20.01.2012, 09:57

3

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <algorithm>
 
int main()
{
    int arr[] = { 12, 16, 28 };
    
    std::cout << std::accumulate( arr, arr + sizeof( arr ) / sizeof( *arr ), 0,
    [] ( int a, int b ) -> int
    {
        while ( b ^= a ^= b ^= a %= b );
        return a;
    } );
}



1



HackSign

41 / 41 / 36

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

Сообщений: 151

20.01.2012, 11:02

4

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream.h> 
 
int main() 
{ 
int mass[10]; 
int NOD, count, i, j, k, x, y, g, h; 
float ost;
//ââîä ìàññèâà âðó÷íóþ 
cout<<"Vvedite kolichestvo elementov massiva ot 3 do 10"<<"n"; 
cin>>x; cout<<"n"; 
 
if((x>10)||(x<3)) 
{ 
 cout<<"Error! Nepravilno vvedennoe kolichestvo elementov massiva!!!"<<"n"; 
 cout<<"Press any key to exit programm"<<"n"; 
 getch(); 
 exit(0); 
 } 
 else 
 { 
      //ââîä ìàññèâà âðó÷íóþ 
 
   for(i=0;i<=x; i++) 
   { 
    cout<<"Vvedite "<<i<<" element massiva "; 
    cin>>mass[i]; cout<<"n"; 
    }  
    //íà÷àëüíûé ýòàï âû÷èñëåíèé íàèáîëüøåãî îáùåãî äåëèòåëÿ
    if(mass[0]<mass[1]) 
    { 
     g=mass[1]; 
     h=mass[0]; 
     }
     if(mass[0]>mass[1]) 
     { 
      g=mass[0]; 
      h=mass[1];
      } 
    while(g%h!=0) 
     {
     ost=g%h;  //NOD 
       
     if(ost==0) 
     { 
      NOD=h; 
      break;
      } 
      else{ 
          count=h;
          h=g%h;
          g=count; 
          NOD=h;
          } 
      }     
       
             
    //âû÷èñëåíèå íàèáîëüøåãî îáùåãî äåëèòåëÿ ìàññèâà 
   for(i=x+2;i<=x;i++) 
   { 
     if(NOD<mass[i])  
      { 
       g=mass[i];
       h=NOD;
       }
      else 
       { 
        g=NOD;
        h=mass[i]; 
        }
       while (g%h!=0)
         { 
       if(g%h==0)
       {NOD=h; 
        break; 
         }
       else 
        { 
           count=h;
           h=g%h;
           g=count;
           NOD=h;
           }
         }
       }
     }
   
 
   cout<<"Naibolhiy obshiy delitel massiva"<<" "<<NOD;
   cout<<"Press any key to exit"; 
   getch();
return 0 ;
}



1



0 / 0 / 0

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

Сообщений: 17

20.01.2012, 12:07

 [ТС]

5

Ребят.Подскажите,как создать новый проэкт..чуть я запутался((



0



co6ak

Кошковед

521 / 509 / 63

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

Сообщений: 1,390

20.01.2012, 12:28

6

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
#include <iostream>
#include <limits.h>
 
int main()
{
    int size;
    std::cout << "Enter size: ";
    std::cin  >> size;
    int *arr = new int [size];
    int NOD = INT_MIN;
 
    std::cout << "nEnter array elements: n";
    for ( int i = 0; i < size; i ++ )
    {
            std::cin >> arr[i];
            if ( NOD < arr[i] ) NOD = arr[i];
    }
 
 
    while ( NOD > 1 )
    {
        bool flag = true;
        for ( int i = 0; i < size; i ++ )
            if ( arr[i] % NOD != 0 )
            {
                flag  = false;
                break;
            }
        if ( !flag ) --NOD;
        else
            break;
    }
 
    std::cout << "The answer is : " << NOD;
    std::cin.get();
    std::cin.get();
    return 0;
}



1



41 / 41 / 36

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

Сообщений: 151

20.01.2012, 13:13

7

Дык в Visual studio 2008 довольно просто. выбираешь язык программирования, открывается среда разработки, далее, в меню Файл, создаешь проект, как только проект у тебя открылся, добавляешь в него исходник и компилишь. файловый обозреватель там чтоли, file browser. я уж давно использую Dev-C++. может подзабыл чуток. ну, в общем как-то так.



1



Shman

6 / 6 / 6

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

Сообщений: 216

25.05.2012, 13:02

8

HackSign, что вычисляет первый цикла вашей программы?

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
 //начальный этап вычислений наибольшего общего делителя
    if(mass[0]<mass[1]) 
    { 
     g=mass[1]; 
     h=mass[0]; 
     }
     if(mass[0]>mass[1]) 
     { 
      g=mass[0]; 
      h=mass[1];
      } 
    while(g%h!=0) 
     {
     ost=g%h;  //NOD 
       
     if(ost==0) 
     { 
      NOD=h; 
      break;
      } 
      else{ 
          count=h;
          h=g%h;
          g=count; 
          NOD=h;
          } 
      }

Оссобенно интересует цикл:

C++
1
2
3
4
5
6
7
8
9
10
11
  while(g%h!=0) // Пока остаток от деления g и h элементов станет не равным 0 выполнять цикл.
   { ostatok=g%h;  // находим остаток от деления элементов.
     if(ostatok == 0) // если остаток равен 0, тогда...
      { NOD=h; // НОД - это элемент h.
        break; }  // Прекратить цикл.
     else
     { count=h;
       h=g%h;
       g=count; 
       NOD=h; } 
    }

Если заполнить массив размером 5 чисами: 1, 2, 3, 4, 5. , то НОД = 8, что ест-но неверно. Так зачем этот цикл нужен? Что он делает?

Добавлено через 1 час 6 минут
Пытался что-то придумать сам. Дальше не могу сообразить что делать, помогите!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>  
#include <conio.h> 
#include <stdlib.h> // Модуль для генератора псевдослучайных чисел.
#include <time.h> // Модуль для работы с датой и временем.
#define N 5 // Размер массива.
int main()
{
 int mass[N]; 
 int i, max, nod; 
 
 srand(unsigned(time(NULL))); // Запуск генератора случайных чисел.
 printf("n Massiv iz chisel ot 1 do 5: n");
  for(i=0; i<N; i++)
  {
   mass[i]=rand()%10+1; // Генерируем случайные элемены массива от 1 до 10...   
   printf("n Mass[%d] = %d. ", i, mass[i]); // и выводим их.
  }
  max=mass[0]; // Первый элемент назначаем за максимальный



0



MrGluck

Форумчанин

Эксперт CЭксперт С++

8194 / 5044 / 1437

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

Сообщений: 13,453

25.05.2012, 13:23

9

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <algorithm>
 
int main()
{
    int arr[] = { 12, 16, 28 };
    
    std::cout << std::accumulate( arr, arr + sizeof( arr ) / sizeof( *arr ), 0,
    [] ( int a, int b ) -> int
    {
        while ( b ^= a ^= b ^= a %= b );
        return a;
    } );
}

Не верно с отрицательными числами.
Наверное надо модуль брать.



0



Shman

6 / 6 / 6

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

Сообщений: 216

25.05.2012, 14:27

10

Еще вариант:

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
#include <stdio.h> 
#include <conio.h> 
#include <stdlib.h> 
#include <time.h> 
#define N 4 // Размер массива.
int main()
{
 /* int mass[N]; */
 int mass[N]={8, 6, 4, 2}; // Объявляем массив.
 int i, g, h, x, temp, NOD; 
 bool flag;
 /* srand(unsigned(time(NULL))); // Запуск генератора случайных чисел. */
 printf("n Massiv iz chisel ot 1 do 4: n"); 
  for(i=0; i<N; i++)
  {
   /* mass[i]=rand()%10+1;  */
   printf("n Mass[%d] = %d. ", i, mass[i]);
  }
 
  if(mass[0]<mass[i]) // Если первый элемент массива меньше второго, тогда...
   { g=mass[i]; h=mass[0]; }  // запомининаем след. элемент в перем-ой g, а первый в перем-ой h.
  if(mass[0]>mass[i]) // Если первый элемент массива больше второго, тогда...
   { g=mass[0]; h=mass[i]; } // запомининаем первый элемент в перем-ой g, а след. в перем-ой h.
 
 do // выполнять до тех пор...
   { 
    if(g%h == 0) // если большее число делится на меньшее без остатка, тогда...
     { NOD=h; } // меньшее число и есть НОД.
    else // Иначе.
     { temp=h; 
       h=g%h; // Второе станет остатком от деления.
       g=temp; // А первое число вторым, значения которого записываем во временную переменную.
       NOD=h; } // Пока НОДом будет второе число.
    }     
 while(g%h!=0); // ...пока остаток от деления g и h элементов не перестанет быть равным 0.
  
  if (NOD != 1) // Если НОД не равен 1...
   { printf("n n NOD = %d. n", NOD); } // Выводим результат на экран.
  else 
   { printf("n n Chisla ne imeut obschih deliteley n"); } // Числа не имеют общих делителей.
              
 getch(); 
 return 0;
}

Разультат: 8. Однако неверно, т.к. 8 не делится на 6 без остатка. Поогите найти ошибку.
PS: Генератор случайных чисел временно отключил, чтобы проверить программу на конкретных числах.



0



Shman

6 / 6 / 6

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

Сообщений: 216

27.05.2012, 11:15

11

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 <stdio.h> 
#include <conio.h> 
#include <stdlib.h> 
#include <time.h> 
#define N 5 
int main()
{ /* int mass[N]; */
 int mass[N]={2, 4, 8, 16, 32}; // Объявляем массив.
 int i, g, h, x, temp, NOD; 
 /* srand(unsigned(time(NULL))); // Запуск генератора случайных чисел. */
 printf("n Massiv iz 5 elementov: n"); 
  for(i=0; i<N; i++)
  {
   /* mass[i]=rand()%10+1;  */
   printf("n Mass[%d] = %d. ", i, mass[i]);
  }
 
  if(mass[0]<mass[i]) // Если первый элемент массива меньше второго, тогда...
   { g=mass[i]; h=mass[0]; }  // запомининаем след. элемент в перем-ой g, а первый в перем-ой h.
  if(mass[0]>mass[i]) // Если первый элемент массива больше второго, тогда...
   { g=mass[0]; h=mass[i]; } // запомининаем первый элемент в перем-ой g, а след. в перем-ой h.
 
 do // выполнять до тех пор...
   { 
    if(g%h == 0) // если большее число делится на меньшее без остатка, тогда...
     { NOD=h; } // меньшее число и есть НОД.
    else // Иначе.
     { temp=h; 
       h=g%h; // Второе станет остатком от деления.
       g=temp; // А первое число вторым, значения которого записываем во временную переменную.
       NOD=h; } // Пока НОДом будет второе число.
    }     
 while(g%h!=0); // ...пока остаток от деления g и h элементов не перестанет быть равным 0.
  
  if (NOD != 1) // Если НОД не равен 1...
   { printf("n n NOD = %d. n", NOD); } // Выводим результат на экран.
  else 
   { printf("n n Chisla ne imeut obschih deliteley n"); } // Числа не имеют общих делителей.
              
 getch(); 
 return 0;
}

Программа выдает, что общих делителей не найдено, хотя здесь НОД = 2. Где допущена ошибка?
Генератор случайных чисел временно отключил, чтобы проверить программу на конкретных числах.

Интересно, что когда я уменьшаю массив до 3 элементов и ввожу 2, 4, 8, то НОД находится верно (НОД=2).



0



Shman

6 / 6 / 6

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

Сообщений: 216

31.05.2012, 21:07

12

Кажется нашел в этом форуме решение другими словами .

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
const int N = 5; // Размер массива.
int main()
{
 int mass[N]={2, 16, 64, 32, 2};
 int NOD, i, flag;
 printf("n Massiv iz 5 elementov n"); 
  for(i=0; i<N; i++)
  {
   printf("n Mass[%d] = %d ", i, mass[i]);
  }
 NOD = mass[0]; // Предпологаем, что первый элемент массива - это НОД.
 for(i=1; i<N; i++) 
  if(NOD > mass[i]) // Если предполгаемый НОД больше след. элемент массива, 
     { NOD = mass[i]; } // тогда след.элемент - НОД.
    flag=1; // Флаг на true
    while(flag==1) // Пока флаг = true делаем.
    {
     flag=0; // Флаг = false.
     for(i=0; i<N; i++)
      if(mass[i]%NOD!=0) // Если след. элемент массива делится на предпологаемый НОД без остатка,
         { flag=1; }  // тогда ставим флаг на true.
         NOD--; // Здесь уменьшаем значение НОД. 
    }
  NOD++; // Здесь увеличиваем значение НОД.   
  printf("n n NOD = %d. n", NOD);  
  
 getch(); 
 return 0;
}
 
 
}

Вот только надо подумать как прикрутить работу с отрицательными числами и обойти деление на 0.



0



Improve Article

Save Article

Like Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Like Article

    In this article, we are given two or more numbers/array of numbers and the task is to find the GCD of the given numbers/array elements in JavaScript.

    Examples:

    Input  : arr[] = {1, 2, 3}
    Output : 1
    
    Input  : arr[] = {2, 4, 6, 8}
    Output : 2

    The GCD of three or more numbers equals the product of the prime factors common to all the numbers, but it can also be calculated by repeatedly taking the GCD of pairs of numbers.

    gcd(a, b, c) = gcd(a, gcd(b, c))
                = gcd(gcd(a, b), c)
                = gcd(gcd(a, c), b)

    For an array of elements, we do the following. We will also check for the result if the result at any step becomes 1 we will just return 1 as gcd(1, x) = 1.

    result = arr[0]
    For i = 1 to n-1
      result = GCD(result, arr[i])

    Below is the implementation of the above approach.

    Example: In this example, we will find the GCD of the elements of an array using Javascript.

    Javascript

    <script>

        function gcd(a, b) {

            if (a == 0)

                return b;

            return gcd(b % a, a);

        }

        function findGCD(arr, n) {

            let result = arr[0];

            for (let i = 1; i < n; i++) {

                result = gcd(arr[i], result);

                if (result == 1) {

                    return 1;

                }

            }

            return result;

        }

        let arr = [2, 4, 6, 8, 16];

        let n = arr.length;

        console.log(findGCD(arr, n));   

    </script>

    Output: 

    2

    Last Updated :
    03 Jan, 2023

    Like Article

    Save Article

    Как найти НОК или НОД в python 3.9 в списке из n кол-ва чисел? (Ввод чисел пользователем)
    (н: math.gcd([1 , 2 , 3])

    задан 26 окт 2021 в 16:22

    Romalik Normalik's user avatar

    4

    список из нескольких чисел можно получить следующим образом:

    data = list(map(int, input().split()))
    

    весь код таким образом будет выглядеть так:

    import math
    
    data = list(map(int, input().split()))
    
    gcd = math.gcd(*data)
    lcm = math.lcm(*data)
    
    print(gcd, lcm)
    

    ответ дан 26 окт 2021 в 16:42

    Zhihar's user avatar

    ZhiharZhihar

    36.9k4 золотых знака25 серебряных знаков67 бронзовых знаков

    1

    print ('a = ', end = '')
    
    a = int (input ())
    
    print ('b = ', end = '')
    
    b = int (input ())
    
    p = a * b
    
    while a != 0 and b != 0:
    
        if a > b:
    
            a = a % b
    
        else:
    
            b = b % a
    
    nod = a + b
    
    nok = p // nod
    
    print ('GCD:', nok)
    print ('LDM:', nod)
    

    ответ дан 26 окт 2021 в 16:29

    D3vzer1's user avatar

    2

    НОД и НОК для массива

    Напомню, что НОД (наибольший общий делитель, GCD) для натуральных чисел A и B – максимальное из чисел, на которые A и B делятся без остатка, НОК (наименьшее общее кратное, LCM) – минимальное из чисел, которые делятся на A и B без остатка. Можно реализовать простой и удобный алгоритм поиска НОД и НОК для пары чисел, а для массива натуральных чисел у народа почему-то вызвало затруднения. Между тем, вот такое решение кажется мне простым и правильным:

    #include <stdio.h>
    
    //Реализация для 2 чисел
    long int nod (int x, int y) { return (x?nod(y%x,x):y); }
    long int nok (int x, int y) { return x*y/nod(x,y); }
    //и вернуть nok(x,y) или nod(x,y)
    
    void main () {
     const int n=5;
     int a[n]={24,36,144,48,72},i;
     //НОД для массива:
     long int nd=a[0];
     for (i=1; i<n; i++) nd=nod((nd<a[i]?nd:a[i]),(nd<a[i]?a[i]:nd));
     printf ("nNOD=%ld",nd);
     //НОК для массива:
     long int nk=1;
     for (i=0; i<n; i++) nk=nok(nk,a[i]);
     printf ("nNOK=%ld",nk);
    }

    Или с выводом через <iostream>:

    #include <iostream>
    using namespace std;
    
    long int nod(long int x, long int y) { return (x ? nod(y % x, x) : y); }
    long int nok(long int x, long int y) { return x * y / nod(x, y); }
    
    int main() {
     const int n = 5;
     long int a[n] = { 24, 36, 144, 48, 72 }, i;
     //НОД для массива:
     long int nd = a[0];
     for (i = 1; i < n; i++) nd = nod((nd < a[i] ? nd : a[i]), (nd < a[i] ? a[i] : nd));
     cout << "NOD = " << nd << endl;
     //НОК для массива:
     long int nk = 1;
     for (i = 0; i < n; i++) nk = nok(nk, a[i]);
     cout << "NOK = " << nk << endl;
     return 0; 
    }

    P.S. Начиная со стандарта C++17, можно воспользоваться стандартными средствами, смотрите в комментарии к программе как подключить компиляцию стандарта C++17 в консольном проекте Visual Studio 2019.

    //Включить в свойствах проекта поддержку стандарта C++17:
    // Project, Properties, C/C++, Language, C++ Language Standard, ISO C++17 (/std:c++17)
    #include <iostream>
    #include <numeric>
    using namespace std;
    
    int main() {
     int n = 24, m = 36;
     cout << gcd(n, m) << endl; //НОД, https://en.wikipedia.org/wiki/Greatest_common_divisor
     cout << lcm(n, m) << endl; //НОК, https://en.wikipedia.org/wiki/Least_common_multiple
     return 0;
    }
    

    03.12.2012, 08:46 [17053 просмотра]


    К этой статье пока нет комментариев, Ваш будет первым

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