Подтвердить что ты не робот

С++ алгоритм для вычисления наименьшего общего кратного для нескольких чисел

Есть ли алгоритм С++ для вычисления наименьшего общего кратного для нескольких чисел, например lcm(3,6,12) или lcm(5,7,9,12)?

4b9b3361

Ответ 1

Вы можете использовать std:: accumulate и некоторые вспомогательные функции:

#include <iostream>
#include <numeric>

int gcd(int a, int b)
{
    for (;;)
    {
        if (a == 0) return b;
        b %= a;
        if (b == 0) return a;
        a %= b;
    }
}

int lcm(int a, int b)
{
    int temp = gcd(a, b);

    return temp ? (a / temp * b) : 0;
}

int main()
{
    int arr[] = { 5, 7, 9, 12 };

    int result = std::accumulate(arr, arr + 4, 1, lcm);

    std::cout << result << '\n';
}

Ответ 2

boost предоставляет функции для вычисления lcm из 2 чисел (см. здесь)

Тогда, используя тот факт, что

lcm(a,b,c) = lcm(lcm(a,b),c)

Вы можете легко вычислить lcm для нескольких чисел, а также

Ответ 3

Алгоритм не специфичен для С++. AFAIK, нет стандартной библиотечной функции.

Чтобы вычислить LCM, вы сначала вычисляете GCD (Greatest Common Divisor) с использованием алгоритма Евклидов.

http://en.wikipedia.org/wiki/Greatest_common_divisor

Алгоритм GCD обычно задается для двух параметров, но...

GCD (a, b, c) = GCD (a, GCD (b, c))
              = GCD (b, GCD (a, c))
              = GCD (c, GCD (a, b))
              = ...

Чтобы вычислить LCM, используйте...

                a * b
LCM (a, b) = ----------
             GCD (a, b)

Логика для этого основана на простой факторизации. Более общий вид (более двух переменных)...

                                          a                 b        
LCM (a, b, ...) = GCD (a, b, ...) * --------------- * --------------- * ...
                                    GCD (a, b, ...)   GCD (a, b, ...)

EDIT - на самом деле, я думаю, что последний бит может быть неправильным. Однако первый LCM (для двух параметров) является правильным.

Ответ 4

Используя GCC с С++ 14, следующий код работал у меня:

#include <algorithm>
#include <vector>

std::vector<int> v{4, 6, 10};    
auto lcm = std::accumulate(v.begin(), v.end(), 1, [](auto & a, auto & b) {
    return abs(a * b) / std::__gcd(a, b);
});

В С++ 17 есть функция std:: lcm (http://en.cppreference.com/w/cpp/numeric/lcm), которая может быть использована для непосредственного накопления.

Ответ 5

С С++ 17 вы можете использовать std::lcm.

И вот небольшая программа, которая показывает, как специализировать ее для нескольких параметров

#include <numeric>
#include <iostream>

namespace math {

    template <typename M, typename N>
    constexpr auto lcm(const M& m, const N& n) {
        return std::lcm(m, n);
    }

    template <typename M, typename ...Rest>
    constexpr auto lcm(const M& first, const Rest&... rest) {
        return std::lcm(first, lcm(rest...));
    }
}

auto main() -> int {
    std::cout << math::lcm(3, 6, 12, 36) << std::endl;
    return 0;
}

Протестируйте его здесь: https://wandbox.org/permlink/25jVinGytpvPaS4v

Ответ 6

Не встроен в стандартную библиотеку. Вам нужно либо построить его самостоятельно, либо получить библиотеку, которая это сделала. Уверен, что у Boost есть один...

Ответ 7

Я только что создал gcd для нескольких чисел:

#include <iostream>    
using namespace std;
int dbd(int n, int k, int y = 0);
int main()
{
    int h = 0, n, s;
    cin >> n;
    s = dbd(n, h);
    cout << s;
}

int dbd(int n, int k, int y){
        int d, x, h;
        cin >> x;
        while(x != y){
            if(y == 0){
                break;
            }
            if( x > y){
                x = x - y;
            }else{
                y = y - x;
            }
        }
        d = x;
        k++;
        if(k != n){
        d = dbd(n, k, x);
        }
    return d;
}

dbd - gcd.

n - количество чисел.

Ответ 8

/*

Copyright (c) 2011, Louis-Philippe Lessard
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

unsigned gcd ( unsigned a, unsigned b );
unsigned gcd_arr(unsigned * n, unsigned size);
unsigned lcm(unsigned a, unsigned b);
unsigned lcm_arr(unsigned * n, unsigned size);
int main()
{
    unsigned test1[] = {8, 9, 12, 13, 39, 7, 16, 24, 26, 15};
    unsigned test2[] = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
    unsigned result;

    result = gcd_arr(test1, sizeof(test1) / sizeof(test1[0]));
    result = gcd_arr(test2, sizeof(test2) / sizeof(test2[0]));
    result = lcm_arr(test1, sizeof(test1) / sizeof(test1[0]));
    result = lcm_arr(test2, sizeof(test2) / sizeof(test2[0]));

    return result;
}


/**
* Find the greatest common divisor of 2 numbers
* See http://en.wikipedia.org/wiki/Greatest_common_divisor
*
* @param[in] a First number
* @param[in] b Second number
* @return greatest common divisor
*/
unsigned gcd ( unsigned a, unsigned b )
{
    unsigned c;
    while ( a != 0 )
    {
        c = a;
        a = b%a;
        b = c;
    }
    return b;
}

/**
* Find the least common multiple of 2 numbers
* See http://en.wikipedia.org/wiki/Least_common_multiple
*
* @param[in] a First number
* @param[in] b Second number
* @return least common multiple
*/
unsigned lcm(unsigned a, unsigned b)
{
    return (b / gcd(a, b) ) * a;
}

/**
* Find the greatest common divisor of an array of numbers
* See http://en.wikipedia.org/wiki/Greatest_common_divisor
*
* @param[in] n Pointer to an array of number
* @param[in] size Size of the array
* @return greatest common divisor
*/
unsigned gcd_arr(unsigned * n, unsigned size)
{
    unsigned last_gcd, i;
    if(size < 2) return 0;

    last_gcd = gcd(n[0], n[1]);

    for(i=2; i < size; i++)
    {
        last_gcd = gcd(last_gcd, n[i]);
    }

    return last_gcd;
}

/**
* Find the least common multiple of an array of numbers
* See http://en.wikipedia.org/wiki/Least_common_multiple
*
* @param[in] n Pointer to an array of number
* @param[in] size Size of the array
* @return least common multiple
*/
unsigned lcm_arr(unsigned * n, unsigned size)
{
    unsigned last_lcm, i;

    if(size < 2) return 0;

    last_lcm = lcm(n[0], n[1]);

    for(i=2; i < size; i++)
    {
        last_lcm = lcm(last_lcm, n[i]);
    }

    return last_lcm;
}

Ссылка на исходный код

Ответ 9

Вы можете рассчитать LCM и или GCM в boost следующим образом:

#include <boost/math/common_factor.hpp>
#include <algorithm>
#include <iterator>


int main()
{
    using std::cout;
    using std::endl;

    cout << "The GCD and LCM of 6 and 15 are "
     << boost::math::gcd(6, 15) << " and "
     << boost::math::lcm(6, 15) << ", respectively."
     << endl;

    cout << "The GCD and LCM of 8 and 9 are "
     << boost::math::static_gcd<8, 9>::value
     << " and "
     << boost::math::static_lcm<8, 9>::value
     << ", respectively." << endl;
}

(Пример взята из http://www.boost.org/doc/libs/1_31_0/libs/math/doc/common_factor.html)

Ответ 10

Коды, приведенные выше, обсуждают только об оценке LCM для нескольких номеров, однако очень вероятно, что при выполнении умножений мы можем переполнение целочисленного предела для данных типа

* Угловой корпус: - *

например. если при оценке вы достигнете такой ситуации, что если LCM_till_now = 1000000000000000 next_number_in_list = 99999999999999 и, следовательно, GCD = 1 (поскольку оба они относительно взаимно просты друг с другом)

Итак, если вы выполняете операцию (LCM_till_now * next_number_in_list), то даже не вписывается в "unsigned long long int"

Устранение: - 1. Используйте большой целочисленный класс 2.Or, если проблема запрашивает LCM% MOD ----------- > , тогда примените свойства модульной арифметики.

Ответ 11

Я нашел это при поиске аналогичной проблемы и хотел внести свой вклад в два числа.

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    cin >> x >> y;

    // zero is not a common multiple so error out
    if (x * y == 0)
        return -1;

    int n = min(x, y);
    while (max(x, y) % n)
        n--;

    cout << n << endl;
}

Ответ 12

Используя тот факт, что lcm должен быть делимым по всем номерам в списке. Здесь список - это вектор, содержащий числа

        int lcm=*(len.begin());
    int ini=lcm;
    int val;
    int i=1;
    for(it=len.begin()+1;it!=len.end();it++)
    {
        val=*it;
        while(lcm%(val)!=0)
        {
            lcm+=ini;
        }
        ini=lcm;
    }
    printf("%llu\n",lcm);
    len.clear();

Ответ 13

Если вы посмотрите эту страницу, вы можете увидеть довольно простой алгоритм, который вы могли бы использовать.: -)

Я не говорю об этом эффективно или что-то в этом духе, но он концептуально масштабируется до нескольких чисел. Вам нужно только пространство для отслеживания ваших исходных номеров и клонированного набора, которым вы управляете, пока не найдете LCM.

Ответ 14

#include
#include

void main()
{
    clrscr();

    int x,y,gcd=1;

    cout<>x;

    cout<>y;

    for(int i=1;i<1000;++i)
    {
        if((x%i==0)&&(y%i==0))
        gcd=i;
    }

    cout<<"\n\n\nGCD :"<
    cout<<"\n\n\nLCM :"<<(x*y)/gcd;

    getch();
}

Ответ 15

  • пусть набор чисел, lcm которых вы хотите рассчитать, будет тета
  • пусть i, множитель, be = 1
  • пусть x = наибольшее число в тете
  • x * i
  • если для каждого элемента j в theta, (x * i)% j = 0, то x * я является наименьшим LCM
  • if not, loop и increment я на 1