总结巨大的斐波纳契数(高达10 ^ 18)

时间:2016-07-20 15:43:46

标签: java algorithm

我最近遇到了一个问题:给定lr你需要找出所有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());

    }
}

1 个答案:

答案 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));
}