在p是素数的情况下,如何有效地找到gcd(a,b)%p?

时间:2018-08-11 10:30:47

标签: java algorithm primes number-theory greatest-common-divisor

我的方法很简单:

  • 首先,使用Euclid 算法找到gcd(a,b)
  • 然后使用p=10^9+7
  • 取出mod

但是我需要一种有效的方法(只需要正确的轨道而不是代码):

ab的值可以在1 10^12 之间,而p {{ 1}}

1 个答案:

答案 0 :(得分:1)

如果您遇到问题,这将是我的解决方案。在我的解决方案中,我检查long的范围是否可以满足10^12。如您所见,以下代码给出了18,这没关系!但是,我不喜欢Euclid的GCD,因为它可以递归地工作。您的范围确实很大的事实会导致消耗大量内存。因此,我更喜欢Binary GCD Algorithm

class Test {
    private static final long P = (long)Math.pow(10, 9) + 7;

    public static void main(String[] args) {
        // Check whether long is suitable in regards to ranges
        System.out.println((int)Math.log10(Long.MAX_VALUE));
        // Your wish up to 10^12, so it's ok!
        int result = calculate(1, (long) Math.pow(10, 12));
        System.out.println(result);

        result = calculate((long) Math.pow(10, 12), (long) Math.pow(10, 12));
        System.out.println(result);
    }

    public static int calculate(long a, long b) {
        return  (int)(gcd(a, b) % P);
    }

    private static long gcd(long p, long q) {
        // https://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html
        if (q == 0) return p;
        if (p == 0) return q;

        // p and q even
        if ((p & 1) == 0 && (q & 1) == 0) return gcd(p >> 1, q >> 1) << 1;

            // p is even, q is odd
        else if ((p & 1) == 0) return gcd(p >> 1, q);

            // p is odd, q is even
        else if ((q & 1) == 0) return gcd(p, q >> 1);

            // p and q odd, p >= q
        else if (p >= q) return gcd((p-q) >> 1, q);

            // p and q odd, p < q
        else return gcd(p, (q-p) >> 1);
    }

    private static long EuclidianGCD(long a, long b) { return b==0 ? a : EuclidianGCD(b, a%b); }

}

您可以从here中查看最后一个答案。此外,如果您坚持使用Euclid的GCD,请尝试一下,它可能会卡住!恕我直言,这根本不高效。