我最近遇到了一个问题:给定l
和r
你需要找出所有x的总和,使得l< = x< = r(mod10 ^ 9 + 7) )。
和,
1 <= l <= r <= 10^18
令sum(x)为斐波那契数的总和至x
,并且将fibo(x)设为xth
斐波那契数。众所周知
sum(x) = fibo(x+2) - 1
使用这个我用this post来计算O(logn)时间内的第n个斐波纳契项。 我想知道它是否可以比这更快地完成。以下是我的实施
public class FastFibonacci {
private static Map<BigInteger, BigInteger> map;
private static BigInteger mod = BigInteger.valueOf(1000000007);
public static BigInteger nthFibonacci(BigInteger num) {
if (num.compareTo(BigInteger.valueOf(2)) <= 0) return BigInteger.ONE;
return solve(num.subtract(BigInteger.ONE)).mod(BigInteger.valueOf(10000));
}
public static BigInteger solve(BigInteger num) {
if (map.get(num) != null) {
return map.get(num);
} else {
BigInteger k = num.divide(BigInteger.valueOf(2));
if (num.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
// f(2*k)
map.put(num, (solve(k).multiply(solve(k)).mod(mod).add(solve(k.subtract(BigInteger.ONE)).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod)).mod(mod)));
return map.get(num);
} else {
// f(2*k + 1)
map.put(num, (solve(k).multiply(solve(k.add( BigInteger.ONE))).mod(mod).add(solve(k).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod))).mod(mod));
return map.get(num);
}
}
}
public static void main(String[] args) {
InputReader in = new InputReader(System.in);
map = new HashMap<>();
map.put(BigInteger.ZERO, BigInteger.ONE);
map.put(BigInteger.ONE, BigInteger.ONE);
int test = in.nextInt();
BigInteger[] ls = new BigInteger[test];
BigInteger[] rs = new BigInteger[test];
for (int i = 0; i < test; i++) {
ls[i] = new BigInteger(in.readString());
rs[i] = new BigInteger(in.readString());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < test; i++) {
BigInteger sumUptoL = nthFibonacci(ls[i]).subtract(BigInteger.ONE);
BigInteger sumUptoR = nthFibonacci(rs[i].add(BigInteger.valueOf(1))).subtract(BigInteger.ONE);
sb.append(sumUptoR.subtract(sumUptoL));
sb.append("\n");
}
System.out.print(sb.toString());
}
}
答案 0 :(得分:0)
假设对于给定的数字N,您只想知道fib(N + 2)-1并且您不需要显示所有序列,您可以使用非递归方法。以下函数使用double,但您可以将其重构为BigInteger以接受更大的值:
public double getFibonacci(int n) {
double f1 = Math.pow(((1 + Math.sqrt(5)) / 2.0), n);
double f2 = Math.pow(((1 - Math.sqrt(5)) / 2.0), n);
return Math.floor((f1 - f2) / Math.sqrt(5));
}