首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在不生成整数的情况下找到第一个k位斐波那契数?

如何在不生成整数的情况下找到第一个k位斐波那契数?
EN

Stack Overflow用户
提问于 2015-10-03 19:18:11
回答 1查看 1.5K关注 0票数 4

我必须找到所有斐波纳契数的第一个k位数,直到斐波那契数列2*10^6。

很明显,我们不能将斐波那契数的值存储在任何变量中。即使计算所有的斐波那契数本身也要花费大量的计算时间。那么,有没有办法只得到斐波那契数的前k位,而不生成整个数呢?

EN

回答 1

Stack Overflow用户

发布于 2015-10-03 20:41:27

这里有一种方法,它不会生成所有的数字。当涉及到快速找到斐波那契数时,有一个O(k log n)过程,其中O(k)是将F(n)F(n-1)相乘所需的时间。它利用了F(n)恰好是矩阵aa[0][1]元素这一事实,这是简单矩阵(reference)n-th幂。所以你可以使用exponentiation by squaring。下面是一个简单的python实现:

代码语言:javascript
运行
复制
def matrix_mult(a, b):
    return ((a[0][0]*b[0][0] + a[0][1]*b[1][0], 
             a[0][0]*b[0][1] + a[0][1]*b[1][1]),
            (a[1][0]*b[0][0] + a[1][1]*b[1][0], 
             a[1][0]*b[0][1] + a[1][1]*b[1][1]))


def matrix_pow(a, k):
    if k == 0:
        return ((1, 0), (0, 1))
    t = matrix_pow(a, k//2)
    t2 = matrix_mult(t, t)
    if k % 2 == 0:
        return t2
    return matrix_mult(t2, a)


def fib(n):
    a = ((1, 1), (1, 0))
    return matrix_pow(a, n)[0][1]


def get_first_k(n, k):
    return str(fib(n))[:k]

for n in range(10 ** 2, 10 ** 2 + 10):
    print(get_first_k(n, 3))

#output
#first 3 digits   actual number
354               #354224848179261915075
573               #573147844013817084101
927               #927372692193078999176
150               #1500520536206896083277
242               #2427893228399975082453
392               #3928413764606871165730
635               #6356306993006846248183
102               #10284720757613717413913
166               #16641027750620563662096
269               #26925748508234281076009

对于n = 2 * 10 ** 5,它需要大约5s来计算F_n,考虑到问题的性质,这是合理的。

以下是Java的替代方案

代码语言:javascript
运行
复制
package stackoverflow;

import java.math.BigInteger;

public class Fibonacci {

    public static class Matrix {
        BigInteger[][] a;

        public Matrix(BigInteger n0, BigInteger n1, BigInteger n2, BigInteger n3) {
            a = new BigInteger[][]{{n0, n1}, {n2, n3}};
        }

        public BigInteger get(int i, int j) {
            return a[i][j];
        }

        @Override
        public String toString() {
            return String.format("%s %s\n%s %s", a[0][0], a[0][1], a[1][0], a[1][1]);
        }
    }

    Matrix matrixMult(Matrix a, Matrix b) {
        return new Matrix(a.get(0, 0).multiply(b.get(0, 0)).add(a.get(0, 1).multiply(b.get(1, 0))),
                          a.get(0, 0).multiply(b.get(0, 1)).add(a.get(0, 1).multiply(b.get(1, 1))),
                          a.get(1, 0).multiply(b.get(0, 0)).add(a.get(1, 1).multiply(b.get(1, 0))),
                          a.get(1, 0).multiply(b.get(0, 1)).add(a.get(1, 1).multiply(b.get(1, 1))));
    }

    Matrix power(Matrix a, int k) {
        if (k == 0)
            return new Matrix(new BigInteger("1"), new BigInteger("0"),
                              new BigInteger("0"), new BigInteger("1"));
        Matrix t = power(a, k / 2);
        Matrix t2 = matrixMult(t, t);
        if (k % 2 == 0)
            return t2;
        return matrixMult(t2, a);
    }

    BigInteger get(int n) {
        Matrix a = new Matrix(new BigInteger("1"), new BigInteger("1"),
                              new BigInteger("1"), new BigInteger("0"));
        return power(a, n).get(0, 1);
    }

    String getFirstK(int n, int k) {
        return get(n).toString().substring(0, k);
    }

    public static void main(String[] args) {
        Fibonacci f = new Fibonacci();

        System.out.println(f.getFirstK(200000, 10));
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32921924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档