我今天在开发人员工作面试中遇到了以下情况,这是问题之一,只有一个我没有回答。
连接数 NN 次,然后计算他的模数到 2017 年。
例如:对于 N=5,数字将为 55555,结果将为 Mod(55555,2017) = 1096 对于 N=10,数字将为 10101010101010101010,结果 Mod(10101010101010101010,2017) = 1197
现在我必须计算的数字是 58184241583791680。我得到的唯一提示是 58184241583791680 连接 58184241583791680 乘以模数 2017 的结果是一个 4 位数字。
我在 math.stackexchange 上发布了这个问题,我得到了解决这个问题的数学方法,而不是蛮力。
我用JAVA编写了以下代码
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
public class Puzzle {
final static BigInteger M = new BigInteger("2017");
public static void main(String [ ] args) {
for (long n : new long[] { 1L, 2L, 5L, 10L, 20L }) {
System.out.println(n + " --> " + bruteForce(n) + " --- " + formulaV2(n));
}
}
private static BigInteger bruteForce(long n) {
String s = "";
for (long i = 0; i < n; i++) {
s = s + n;
}
return new BigInteger(s.toString()).mod(M);
}
private static BigInteger formulaV2(long n) {
String aux = String.valueOf(n);
long L = aux.length();
long K = n;
double op1 = Math.pow(10,L*K);
BigDecimal minus1 = new BigDecimal(1);
BigDecimal p1 = new BigDecimal(op1).subtract(minus1);
double op2 = Math.pow(10,L);
BigDecimal p2 = new BigDecimal(op2).subtract(minus1).pow(-1,MathContext.DECIMAL64);
BigDecimal R = new BigDecimal(n).multiply(p1).multiply(p2);
R = R.setScale(0,BigDecimal.ROUND_UP);
BigInteger ret = R.toBigInteger();
return ret.mod(M);
}
}
我正在使用 BigInteger 和 BigDecimal,因为我想获得非常大的数字(16 位以上)的值。
bruteForce 方法将简单地连接循环内的数字,而 formulaV2 方法将使用数学论坛中提出的问题中的公式。
bruteForce 方法仅用于验证。
然而,公式方法适用于 N<10,但不适用于 N>=10。在 N=10 我得到不正确的结果。
编码似乎与提供的公式一致(至少对我来说,也许我缺少一些东西),并且公式是正确的(我在 Wolfram Alpha 中检查过)。
我的猜测是我有精度问题,也许 BigDecimal 在这种情况下不是正确的对象?