【问题标题】:How to find lcm of multiple numbers using GCD approach?如何使用 GCD 方法找到多个数字的 lcm?
【发布时间】:2015-07-28 01:42:22
【问题描述】:

我正在使用欧几里得方法,即 LCM = num1 * num2 / gcd ( num1 , num2 ) 我已经成功地为两个数字编写了代码,但是如果我尝试将它用于多个输入,那就是错误的。 我的方法可以表示为 lcm(a,b,c) = lcm(a,lcm(b,c)) 但是这种方法不起作用,因为它们(lcm(a,b,c)和 lcm(a,lcm(b,c))) 是两个不同的值。

【问题讨论】:

  • 你的方法应该有效。如果没有,那么您的实现中存在错误,在这种情况下,如果您无法弄清楚它是什么,您应该发布您的代码。
  • 也许你的中间数字溢出了数据类型?
  • 您是否尝试过:LCM = num1 / gcd ( num1 , num2 ) * num2,以避免溢出?

标签: algorithm function lcm


【解决方案1】:

我在 C++ 中使用 Sieves of Eratosthenes 计算 LCM,如下所示:

int lcm(int *a,int N,bool _sorted=false)    // least common multiple of a[N]
    {                                       // if sorted a[N] must be: (a0 > a1 > a2 > ... > aN)
    if (N<1) return 0;
    int i,j,c,dc;
    int *b=new int[N];
    if (_sorted) for (i=0;i<N;i++) b[i]=a[i];   // b[N] = a[N]
    else for (c=0x7FFFFFFF,j=0;j<N;j++,c=dc)    // b[N] = insert sort a[N]
        {
        for (dc=0,i=0;i<N;i++)
         if ((dc<a[i])&&(c>a[i])) dc=a[i];
        if (!dc) { N=j; break; }
        b[j]=dc;
        }
    // replace duplicit multiplies with 1
    for (i=  0;i<N;i++) if (b[i]>1)
    for (j=i+1;j<N;j++) if (b[j]>1)
     if (b[i]%b[j]==0) b[j]=1;
    // cut off all ones
    for (j=0,i=0;i<N;i++) if (b[i]>1) { b[j]=b[i]; j++; } N=j;
    if (N<1) return 1;
    // lcm
    for (dc=b[0],i=-1,c=dc;i<0;c+=dc)
     for (i=1;i<N;i++)
      if (c%b[i]!=0) { i=-1; break; }
    c-=dc;
    delete[] b;
    return c;
    }
  • 首先确保输入的数字降序排列(b[]数组)
  • 它是旧代码的剩余部分,您只需要在b[0] 中拥有最大的 num
  • 然后删除重复的倍数(例如 8,4,2 ... 仅使用 8)
  • 最后使用筛子
  • 您实际上不需要将筛子存储在内存中
  • 而只是增量计算筛子
  • 并且只记住最大数的倍数c
  • 如果所有其余数字都可整除,则您找到了结果

[edit2] gcd 的使用

//--------------------------------------------------------------------------
int gcd(int a0,int a1)
    {
    int d,r,r0;
    if (a0<a1) { r=a0; a0=a1; a1=r; }
    // euklid a0/a1
    d=a0/a1;
    r=a0%a1; r0=r;
    if (!r) return a1;
    // a1/r0
    d=a1/r0;
    r=a1%r0;
    if (!r) return r0;
    a0=r0; a1=r;
    for (;;)
        {
        if (a0<a1) { r=a0; a0=a1; a1=r; }
        d=a0/a1;
        r=a0%a1;
        if (!r) return a1;
        a0=a1; a1=r;
        }
    return 0;
    }
//--------------------------------------------------------------------------    
int lcm(int *a,int N)                               // least common multiple of a[N]
        {
        int a0,a1,aa;
        if (N==0) return 0;
        if (N==1) return a[0];
        a0=a[0];
        if (N==2) a1=a[1]; else a1=lcm(a+1,N-1);
        aa=gcd(a0,a1);
        if (N==2) return (a0*a1)/aa;
        return (a1/aa)*a0;
        }
//--------------------------------------------------------------------------
  • 这比筛子快得多...

【讨论】:

  • 这怎么可能更快? OP 的方法是 O(n log W),其中 n 是元素的数量,W 是最大值。您的情况类似于 O(W log W),这要糟糕得多。还有什么需要mul/div?通过在乘法之前除以 gcd 并使用 64 位整数(即int64_t),您可以更轻松地避免溢出。
猜你喜欢
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多