Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 动态规划中的n个Fibonacci数_Java_Algorithm_Scala - Fatal编程技术网

Java 动态规划中的n个Fibonacci数

Java 动态规划中的n个Fibonacci数,java,algorithm,scala,Java,Algorithm,Scala,每个人都知道斐波那契级数的逻辑 Fib0 = 0 Fib1 = 1 Fibn = Fibn-1 + Fibn-2 , n > 1 我的问题是我必须计算fib(n)%(100000000+7),并且输出应符合n 类似于n=0输出1的 用于n=5输出5 用于n=10输出55 用于n=100输出24278230 我还成功地用scala中的tail递归对它进行了编码 def fi( n : Int) : Long = { def fib_tail( n: Int, a:Int, b:Int

每个人都知道斐波那契级数的逻辑

Fib0 = 0
Fib1 = 1
Fibn = Fibn-1 + Fibn-2 , n > 1
我的问题是我必须计算
fib(n)%(100000000+7)
,并且输出应符合
n

类似于n=0输出1的

用于n=5输出5

用于n=10输出55

用于n=100输出24278230

我还成功地用
scala中的
tail递归
对它进行了编码

def fi( n : Int) : Long = { 
  def fib_tail( n: Int, a:Int, b:Int): Int = n match {
    case 0 => a 
    case _ => fib_tail( n-1, b, (a+b))
  }
  return fib_tail( n, 0, 1)
}


   l.map(x=> println(fi(x)%((math.pow(10, 8)).toInt +7  )))
对于0,1,5,10它工作正常,但是对于100我想要
24278230
for
100


任何人给我一些想法来获得这个输出

这是我知道的计算fib%mod的最快方法,但你只看到1000+左右的差异

public static void main(String[] args) {
    long mod = 100_000_007;
    for (int i = 100_000_000; i > 0; i /= 10) {
        long start = System.nanoTime();
        final long l = fibMod3(i, mod);
        long time = System.nanoTime() - start;
        System.out.printf("fib(%,d) %% %,d is %,d took %.1f us to calculate%n", i, mod, l, time / 1e3);
    }
}

// use a simple loop and % each time.
public static long fibMod(int n, long mod) {
    long a = 1, b = 1;
    if (n <= 2) return 1;
    while (n-- > 2) {
        long c = a + b;
        a = b;
        b = c % mod;
    }
    return b;
}

// mod is very expensive so only do this on every third iteration.
public static long fibMod3(int n, long mod) {
    long a = 1, b = 1;
    if (n <= 2) return 1;
    while (n > 5) {
        long c = a + b;
        a = b + c;
        b = (c + a) % mod;
        n -= 3;
    }
    while (n > 2) {
        long c = a + b;
        a = b;
        b = c;
        n--;
    }
    return b % mod;
}

当代码预热时,fib(100)需要0.7微秒。如果循环增加大小,它甚至不会被编译,大约需要3微秒。

这是我所知道的计算fib%mod的最快方法,但你只看到1000+左右的差异

public static void main(String[] args) {
    long mod = 100_000_007;
    for (int i = 100_000_000; i > 0; i /= 10) {
        long start = System.nanoTime();
        final long l = fibMod3(i, mod);
        long time = System.nanoTime() - start;
        System.out.printf("fib(%,d) %% %,d is %,d took %.1f us to calculate%n", i, mod, l, time / 1e3);
    }
}

// use a simple loop and % each time.
public static long fibMod(int n, long mod) {
    long a = 1, b = 1;
    if (n <= 2) return 1;
    while (n-- > 2) {
        long c = a + b;
        a = b;
        b = c % mod;
    }
    return b;
}

// mod is very expensive so only do this on every third iteration.
public static long fibMod3(int n, long mod) {
    long a = 1, b = 1;
    if (n <= 2) return 1;
    while (n > 5) {
        long c = a + b;
        a = b + c;
        b = (c + a) % mod;
        n -= 3;
    }
    while (n > 2) {
        long c = a + b;
        a = b;
        b = c;
        n--;
    }
    return b % mod;
}

当代码预热时,fib(100)需要0.7微秒。如果你的循环越来越大,它甚至没有编译,需要3微秒。

< P>我已经用C++编码了,它工作得很好。
LL fi(int n, LL a, LL b) {
   if (n == 0) {
     return a;
  } else {
     return fi(n-1, b, (a+b) % 100000007);
   }
}

这里应该是:Fib尾部(N-1,B,(A+B)%mod),否则结果将超出范围。

< P>我在C++中对其进行了编码,并且效果良好。
LL fi(int n, LL a, LL b) {
   if (n == 0) {
     return a;
  } else {
     return fi(n-1, b, (a+b) % 100000007);
   }
}

你应该在这里修改:fib_tail(n-1,b,(a+b)%Mod),否则结果将超出Long的范围。

我的答案是一个比较通用的解决方案。你需要一些基本的代数知识才能完全理解它

让我们有一个向量

我们把它和矩阵相乘

我们将收到:

因此,当我们将向量与这个矩阵相乘时,我们得到下一个斐波那契数。但是如果我们把向量乘以T2会发生什么呢

用这种方法,我们在下一个(n+3)后构造斐波那契数。现在,如果我们从这个向量中的前两个斐波那契数开始,用Tn-1相乘,我们会得到什么

因此,通过将向量乘以矩阵T,提升到(n-1)次方,我们可以得到第n个斐波那契数。我们可以通过计算时间O(logn)计算Tn-1。当然,我们应该用模108+7来做所有的计算

以下是我的实现(Java)的链接:

该算法应能很好且快速地适用于n到2108的所有正值

方法的样本运行时间(使用与Peter Lawrey相同的时间测量):

然而,尽管如此,这并不是解决问题的最快算法。众所周知,斐波那契数在某些模下具有周期剩余。引用斐波那契数:

可以看出,如果斐波那契序列的成员取mod n,则得到的序列必须是周期性的,周期最多为n2−一,


换句话说,如果你找到这个周期(例如,线性复杂度),你也可以找到每个fibonacci数模108+7的结果。你需要一些基本的代数知识才能完全理解它

让我们有一个向量

我们把它和矩阵相乘

我们将收到:

因此,当我们将向量与这个矩阵相乘时,我们得到下一个斐波那契数。但是如果我们把向量乘以T2会发生什么呢

用这种方法,我们在下一个(n+3)后构造斐波那契数。现在,如果我们从这个向量中的前两个斐波那契数开始,用Tn-1相乘,我们会得到什么

因此,通过将向量乘以矩阵T,提升到(n-1)次方,我们可以得到第n个斐波那契数。我们可以通过计算时间O(logn)计算Tn-1。当然,我们应该用模108+7来做所有的计算

以下是我的实现(Java)的链接:

该算法应能很好且快速地适用于n到2108的所有正值

方法的样本运行时间(使用与Peter Lawrey相同的时间测量):

然而,尽管如此,这并不是解决问题的最快算法。众所周知,斐波那契数在某些模下具有周期剩余。引用斐波那契数:

可以看出,如果斐波那契序列的成员取mod n,则得到的序列必须是周期性的,周期最多为n2−一,


换句话说,如果你找到这个周期(例如,线性复杂度),你也可以找到每个fibonacci数模108+7的结果。

看看这里:对于一个类似(但不是相同)问题的答案,你想要Java的答案吗?如果使用迭代,速度会快得多。你应该能够在5毫秒内第一次计算fib(100),之后更快。是@PeterLawrey我想要Java的解决方案看看这里:对于一个类似(但不是相同)问题的答案,你想要Java的答案吗?如果使用迭代,速度会快得多。你第一次应该能够在5毫秒内计算fib(100),之后更快。是的@PeterLawrey我想要Java的解决方案它仍然需要O(N)时间。更快的方法是对矩阵使用快速幂算法,计算fib(N)需要O(lgN)。请参考此链接@notbad我怀疑它意味着比
long
中的值大得多,这意味着使用BigInteger,因此成本可能是O((lg n)^2),因为操作成本随着计算值的大小而增加。@yasen那么发布更快的解决方案应该很容易。我对你更快的解决方案很感兴趣(我不是说这不可能实现,但对我来说并不明显)@PeterLawrey是的,我正在研究我的ans