Java 模Fibonacci的解决方案适用于小整数,但不适用于大整数
我正在解决UVa(模斐波那契)的10229问题,代码对小整数很有效,但对大输入(例如n=2.147.483.647)程序似乎卡住了。我检查了multi和pot方法是否可以创建一个无限循环,但multi和pot似乎都不是问题所在。对于输入n=21474836647和m=4,multi有49个调用,pot有31个调用,大致正确。那么,问题出在哪里呢Java 模Fibonacci的解决方案适用于小整数,但不适用于大整数,java,Java,我正在解决UVa(模斐波那契)的10229问题,代码对小整数很有效,但对大输入(例如n=2.147.483.647)程序似乎卡住了。我检查了multi和pot方法是否可以创建一个无限循环,但multi和pot似乎都不是问题所在。对于输入n=21474836647和m=4,multi有49个调用,pot有31个调用,大致正确。那么,问题出在哪里呢 import java.math.BigInteger; import java.math.BigDecimal; import java.util.S
import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.Scanner;
class Main {
class Matrix {
BigInteger[] values;
public Matrix(BigInteger a, BigInteger b, BigInteger c, BigInteger d) {
values = new BigInteger[4];
values[0] = a;
values[1] = b;
values[2] = c;
values[3] = d;
}
public Matrix multi(Matrix m1, Matrix m2) {
Matrix result;
BigInteger[] p = new BigInteger[7];
BigInteger[] q = new BigInteger[4];
//Strassen Algorithm
p[0] = m1.values[0].multiply(m2.values[1].subtract(m2.values[3]));
p[1] = m2.values[3].multiply(m1.values[0].add(m1.values[1]));
p[2] = m2.values[0].multiply(m1.values[2].add(m1.values[3]));
p[3] = m1.values[3].multiply(m2.values[2].subtract(m2.values[0]));
p[4] = (m1.values[0].add(m1.values[3])).multiply(m2.values[0].add(m2.values[3]));
p[5] = (m1.values[1].subtract(m1.values[3])).multiply(m2.values[2].add(m2.values[3]));
p[6] = (m1.values[0].subtract(m1.values[2])).multiply(m2.values[0].add(m2.values[1]));
q[0] = ((p[4].add(p[3])).subtract(p[1])).add(p[5]);
q[1] = p[0].add(p[1]);
q[2] = p[2].add(p[3]);
q[3] = ((p[4].add(p[0])).subtract(p[2])).subtract(p[6]);
result = new Matrix(q[0], q[1], q[2], q[3]);
return result;
}
public Matrix pot(Matrix m1, int n) {
Matrix x;
// Exponentiation by Squaring (for matrices)
if (n == 0) {
return new Matrix(BigInteger.ONE, BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE);
} else if (n == 1) {
return m1;
} else {
x = pot(m1, n/2);
if (n % 2 == 0) {
return multi(x, x);
} else {
return multi(multi(m1, x), x);
}
}
}
}
public static void main(String args[]) {
Matrix inicial, atual;
int n, m;
BigInteger M, power;
Scanner in = new Scanner(System.in);
inicial = new Matrix(BigInteger.ONE, BigInteger.ONE, BigInteger.ONE, BigInteger.ZERO);
while (in.hasNextLine()) {
n = in.nextInt();
m = in.nextInt();
atual = Matrix.pot(inicial, n);
power = new BigDecimal(Math.pow(2, m)).toBigInteger();
M = atual.values[1].mod(power);
System.out.println(M);
}
}
}
我不认为它卡住了。我想这需要很长时间。我接受了您的代码并添加了几行代码来确定运行时间
long start = System.nanoTime();
atual = Matrix.pot(inicial, n);
power = new BigDecimal(Math.pow(2, m)).toBigInteger();
M = atual.values[1].mod(power);
long end = System.nanoTime();
long runns = (end - start);
double runs = ((double)runns)/1000000000.0;
System.out.println(M);
System.out.println(runs);
用10000000(一千万)和4运行它,需要4.3秒。以2000万和4的速度运行,需要11.8秒。五千万和四只花了38秒。与2147483647一起运行?要花很长时间。至少几个小时。你所在学校的问题编号和课程名称对世界其他地方来说没有任何意义,即使它是一所像UVa那么大的学校。我完全不知道你的程序打算做什么,除了“它卡住了”之外,你没有提供任何信息。对于“卡住”我通常推荐一个调试器。。。你试过了吗?你也应该仔细检查你的代码,记住矩阵乘法是不可交换的<代码>m1*m2!=m2*m1。令人困惑的是,您正在声明一个方法
multi(矩阵m1,矩阵xm2)
,据我所知,您正在返回m2*m1
,这是基于我对的阅读和您的代码正在执行的操作。现在,我很可能错了-很难从这段代码中分辨出来,因为你的p0到p6的顺序与维基百科中的条目不同。很抱歉,缺少信息。我提到的问题是。对于陷入困境,我的意思是,对于像117、116和其他许多小输入,程序输出正确的答案,但对于我给出的大示例,什么都没有发生。我回顾了我的Strassen算法的实现,但它似乎工作得很好,因为它输出的结果与矩阵乘法的标准算法相同。