Java 当p是素数时,如何有效地求gcd(a,b)%p?
我的方法很简单:Java 当p是素数时,如何有效地求gcd(a,b)%p?,java,algorithm,primes,number-theory,greatest-common-divisor,Java,Algorithm,Primes,Number Theory,Greatest Common Divisor,我的方法很简单: 首先,使用欧几里德算法查找gcd(a,b)。 然后用p=10^9+7取出mod 但我需要一种有效的方法(只需要正确的轨道而不是代码): a和b的值可能介于1到10^12之间,而p是prime 10^9+7如果我有你这样的问题,这将是我的解决方案。在我的解决方案中,我检查long的范围是否满足10^12。如您所见,下面的代码给出了18,这意味着它没问题!尽管如此,我还是不喜欢欧几里德的GCD,因为它递归地工作。你的范围真的很大,这会消耗大量内存。所以,我更喜欢 类测试{ 私有
- 首先,使用欧几里德算法查找
。gcd(a,b)
- 然后用
p=10^9+7取出mod
a
和b
的值可能介于1
到10^12
之间,而p
是prime 10^9+7
如果我有你这样的问题,这将是我的解决方案。在我的解决方案中,我检查long
的范围是否满足10^12
。如您所见,下面的代码给出了18
,这意味着它没问题!尽管如此,我还是不喜欢欧几里德的GCD,因为它递归地工作。你的范围真的很大,这会消耗大量内存。所以,我更喜欢
类测试{
私有静态最终长P=(长)数学.pow(10,9)+7;
公共静态void main(字符串[]args){
//检查long是否适用于范围
System.out.println((int)Math.log10(Long.MAX_值));
//你的愿望达到10^12,所以没关系!
int结果=计算(1,(长)数学功率(10,12));
系统输出打印项次(结果);
结果=计算((长)数学功率(10,12),(长)数学功率(10,12));
系统输出打印项次(结果);
}
公共静态整数计算(长a、长b){
返回值(整数)(gcd(a,b)%P);
}
专用静态长gcd(长p、长q){
// https://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html
如果(q==0)返回p;
如果(p==0)返回q;
//p和q偶数
如果((p&1)==0&(q&1)==0)返回gcd(p>>1,q>>1)>1,q);
//p是奇数,q是偶数
否则如果((q&1)==0)返回gcd(p,q>>1);
//p和q奇数,p>=q
否则,如果(p>=q)返回gcd((p-q)>>1,q);
//p和q奇数,p>1);
}
私有静态长欧几里得GCD(长a,长b){返回b==0?a:EuclidianGCD(b,a%b);}
}
您可以从中查看最后一个的答案。此外,如果你坚持使用欧几里德的GCD,试试看,它可能会卡住!我觉得它根本就没有效率。你的方法有什么问题吗?
尾部递归如何?因此,您不会消耗大量内存,而不仅仅是当前堆栈帧。好吧,既然你说的是Java
,那么你可能不得不选择其他方法。不过,你可以将欧几里德算法实现为一个循环,与二进制GCD相同,因此它们都可以在没有不必要的堆栈空间使用的情况下实现Yupp!我已经试过欧几里德的GCD了。它占用了太多的内存。我会试一下这个二进制GCD或Stein的算法。谢谢@MdUmair你是在解决8月的CodeChef问题吗?如果您在提交时使用了此代码,那么您将面临剽窃处罚。@saketk21这是一个很好的习惯,我希望每个人都有一天, thanks@saketk21是的,你是对的。我当时正在解决长达8月的CodeChef问题,但我已经知道了Stein的算法。我问这个问题的主要原因不是为了在CodeChef获得分数,而是为了在初学者身上学到一些新的东西。我想知道我是否可以通过使用MMI或其他技术在首要的
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); }
}