我正在尝试解决Project Euler#97问题。我不想在网上看,因为他们直接提供解决方案。
这是练习:
发现超过一百万位数的第一个已知素数是 1999年发现,并且是梅森素数的形式2 ^ 6972593-1; 它包含正好2,098,960位数字。随后其他梅森 已找到包含更多数字的2 ^ p-1形式的素数。
然而,在2004年发现了一个巨大的非梅森素数 包含2,357,207位数:28433×2 ^ 7830457 + 1.
找到此素数的最后十位数。
所以,我试过这个:
public static void main(String []args){
BigInteger i = new BigInteger("28433")
.multiply(new BigInteger(String.valueOf(Math.pow(2, 7830457)))
.add(new BigInteger("1")));
String s = i.toString();
System.out.println(s.substring(s.length()-10, s.length()));
}
显然这不起作用:
Exception in thread "main" java.lang.NumberFormatException: For input string: "Infinity"
我应该如何解决这个问题(我真的被困住了)? (请不要给出解决方案,只是提示)
由于
答案 0 :(得分:6)
你有一个问题,你想要答案mod 10 ^ 10(最后十位数)
您可以使用2的幂来更快地计算功率。例如x * x = x ^ 2,并且x ^ 2 * x ^ 2 = x ^ 4等等。 7 830 457 = 0b11101110111101110111001是2 ^ 23 + 2 ^ 22 + 2 ^ 21 + 2 ^ 19 ... 2 ^ 0所以它是x ^(2 ^ 23)* x ^(2 ^ 22)* x(2 ^ 21)* x ^(2 ^ 19)* ... x你必须执行每个操作mod 10 ^ 10以避免溢出。你可以将它乘以第一个常数并加1。
使用这种方法,您可以在O(log N)中计算,其中N是幂。
将为您完成大部分工作的关键功能是BigInteger.modPow它旨在有效地计算大功率,但仅计算数字的最低部分(基于所选的模型)
答案 1 :(得分:0)
问题在于计算2 ^ 7830457
他们想要最后10位数,这意味着数字mod 10000000000
根据这个:http://en.wikipedia.org/wiki/Modulo_operation
ab mod n =((mod n)*(b mod n))mod n
所以你可以在一个循环中使用乘法计算2 ^ 7830457,你在每次乘法后取模数
编辑:递归乘法会更快
public static long pow1(int a,long b,long n){
if (b==1)return a%n;
if (b%2==1){
return (pow1(a,(b-1)/2,n)*a)%n;
}
else{
return (pow1(a,b/2,n))%n;
}
}
答案 2 :(得分:0)
递归代码中缺少一个因素
def pow1(a,b,n):
if (b==1):
return a%n
if (b%2==1):
return (pow1(a,(b-1)//2,n)*pow1(a,b//2,n)*a)%n
else:
return (pow1(a,b//2,n)*pow1(a,b//2,n))%n