【问题标题】:Sum of numbers in a given Fibonacci sequence给定斐波那契数列中的数字总和
【发布时间】:2021-06-28 05:21:22
【问题描述】:

我的任务是确定斐波那契数列中从 A 到 B 的数字之和是否可以被数字 D 整除。

我使用快速加倍算法在数列中找到需要的数,并使用公式:
Fa + ... + Fb sub> = Fb+2 - 1 - (Fa+1 - 1) - 确定级数之和,但这还不够。为了测试,我取了一个从 A = 10,000,000 到 B = 20,000,000 的序列,数字 D = 987654,程序在 3.3 秒内执行,这已经很多了。有没有办法优化我的代码?

class Solution {

    private static Map<BigDecimal, BigDecimal> previousValuesHolder;
    static {
        previousValuesHolder = new HashMap<>();
        previousValuesHolder.put(BigDecimal.ZERO, BigDecimal.ZERO);
        previousValuesHolder.put(BigDecimal.ONE, BigDecimal.ONE);
    }

    private static BigInteger totalSum;

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        int nb = in.nextInt();

        for (int i = 0; i < nb; i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            int d = in.nextInt();

            totalSum = calculateTotalSum(a, b);
            System.out.println(checkSum(totalSum, a, b, d));
        }
    }

    private static BigInteger calculateTotalSum(int start, int finish) {
        BigInteger res1 = fibDoubleFast(finish + 2).subtract(BigInteger.valueOf(1));
        BigInteger res2 = fibDoubleFast(start + 1).subtract(BigInteger.valueOf(1));

        return res1.subtract(res2);
    }

    private static String checkSum(BigInteger sum, int start, int finish, int d) {
        BigInteger result = sum.remainder(BigInteger.valueOf(d));

        return result.longValue() > 0
                ? String.format("F_%s + ... + F_%s is NOT divisible by %s", start, finish, d)
                : String.format("F_%s + ... + F_%s is divisible by %s", start, finish, d);
    }

    private static BigInteger fibDoubleFast(int n) {
        BigInteger a = BigInteger.ZERO;
        BigInteger b = BigInteger.ONE;
        int m = 0;
        for (int bit = Integer.highestOneBit(n); bit != 0; bit >>>= 1) {
            BigInteger d = multiply(a, b.shiftLeft(1).subtract(a));
            BigInteger e = multiply(a, a).add(multiply(b, b));
            a = d;
            b = e;
            m *= 2;

            if ((n & bit) != 0) {
                BigInteger c = a.add(b);
                a = b;
                b = c;
                m++;
            }
        }
        return a;
    }

    private static BigInteger multiply(BigInteger x, BigInteger y) {
        return x.multiply(y);
    }
}

【问题讨论】:

  • codereview.stackexchange.com 可能是这个问题的正确位置。
  • 一旦你有一个可以被 D 整除的数字,不是更好吗?
  • @JoakimDanielson 这没有意义,即使我只输入了 1 行,测试仍然没有及时通过
  • 你误解了我的意思,我的意思是你应该重写 calculateTotalSum 以便它在你找到一个数字后立即返回。无论如何,这更像是一个调查建议,而不是解决方案。
  • 1.当您返回res1.subtract(res2) 时,为res1res2 执行.subtract(BigInteger.valueOf(1)) 毫无意义。 (x - 1) - (y - 1)x - y 相同。 2. 没有理由将totalSum 声明为static 变量。 3. 不要将String.format 用于可以表示为纯字符串连接的内容。 4.删除未使用的东西,previousValuesHolder 没有任何用途,m 永远不会使用。 5. 避免冗余计算的一种简单方法是向multiply添加缓存。

标签: java performance optimization fibonacci


【解决方案1】:

对于较小的 D 值(我认为小于 2^31),您可以使用 long 完成整个代码,并对每个中间结果执行 mod D。

private static long fibDoubleFastModD(int n, long m) {
        ...
        long d = (...) % m;
        long e = (...) % m;
        ...  
}

【讨论】:

    猜你喜欢
    • 2017-05-08
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2015-06-05
    相关资源
    最近更新 更多