17

3 つ以上の数値の最大公約数アルゴリズムを見つける例を教えてください。

プログラミング言語は関係ないと思います。

4

6 に答える 6

33

最初のペアから始めて GCD を取得し、その結果の GCD と次の数字を取得します。明らかな最適化は、実行中の GCD が 1 に達した場合に停止できることです。他の最適化があるかどうかを確認するために、これを監視しています。:)

ああ、操作は交換可能/結合的であるため、これは簡単に並列化できます。

于 2009-08-05T07:53:22.177 に答える
7

3 つの数値の GCD は として計算できますgcd(a, b, c) = gcd(gcd(a, b), c)。ユークリッド アルゴリズム、拡張ユークリッド、またはバイナリ GCD アルゴリズムを繰り返し適用して、答えを得ることができます。残念ながら、GCD を見つける他の (よりスマートな?) 方法は知りません。

于 2009-08-05T07:56:36.177 に答える
1

これに関するWikiページを更新しました。

[ https://en.wikipedia.org/wiki/Binary_GCD_algorithm#C.2B.2B_template_class]

これは、任意の数の項を取ります。GCD(5, 2, 30, 25, 90, 12) を使用します。

template<typename AType> AType GCD(int nargs, ...)
{
    va_list arglist;
    va_start(arglist, nargs);

    AType *terms = new AType[nargs];

    // put values into an array
    for (int i = 0; i < nargs; i++) 
    {
        terms[i] = va_arg(arglist, AType);
        if (terms[i] < 0)
        {
            va_end(arglist);
            return (AType)0;
        }
    }
    va_end(arglist);

    int shift = 0;
    int numEven = 0;
    int numOdd = 0;
    int smallindex = -1;

    do
    {
        numEven = 0;
        numOdd = 0;
        smallindex = -1;

        // count number of even and odd
        for (int i = 0; i < nargs; i++)
        {
            if (terms[i] == 0)
                continue;

            if (terms[i] & 1)
                numOdd++;
            else
                numEven++;

            if ((smallindex < 0) || terms[i] < terms[smallindex])
            {
                smallindex = i;
            }
        }

        // check for exit
        if (numEven + numOdd == 1)
            continue;

        // If everything in S is even, divide everything in S by 2, and then multiply the final answer by 2 at the end.
        if (numOdd == 0)
        {
            shift++;
            for (int i = 0; i < nargs; i++)
            {
                if (terms[i] == 0)
                    continue;

                terms[i] >>= 1;
            }
        }

        // If some numbers in S  are even and some are odd, divide all the even numbers by 2.
        if (numEven > 0 && numOdd > 0)
        {
            for (int i = 0; i < nargs; i++)
            {
                if (terms[i] == 0)
                    continue;

                if ((terms[i] & 1)  == 0) 
                    terms[i] >>= 1;
            }
        }

        //If every number in S is odd, then choose an arbitrary element of S and call it k.
        //Replace every other element, say n, with | n−k | / 2.
        if (numEven == 0)
        {
            for (int i = 0; i < nargs; i++)
            {
                if (i == smallindex || terms[i] == 0)
                    continue;

                terms[i] = abs(terms[i] - terms[smallindex]) >> 1;
            }
        }

    } while (numEven + numOdd > 1);

    // only one remaining element multiply the final answer by 2s at the end.
    for (int i = 0; i < nargs; i++)
    {
        if (terms[i] == 0)
            continue;

        return terms[i] << shift;
    }
    return 0;
};
于 2016-04-21T02:31:47.430 に答える
0

Java の場合 (最適ではありません):

public static int GCD(int[] a){
    int j = 0;

    boolean b=true;
    for (int i = 1; i < a.length; i++) {
        if(a[i]!=a[i-1]){
            b=false;
            break;
        }
    }
    if(b)return a[0];
    j=LeastNonZero(a);
    System.out.println(j);
    for (int i = 0; i < a.length; i++) {
        if(a[i]!=j)a[i]=a[i]-j;
    }
    System.out.println(Arrays.toString(a));
    return GCD(a);
}

public static int LeastNonZero(int[] a){
    int b = 0;
    for (int i : a) {
        if(i!=0){
            if(b==0||i<b)b=i;
        }
    }
    return b;
}
于 2015-05-10T00:21:05.793 に答える