【发布时间】:2016-07-10 06:28:12
【问题描述】:
Stackoverflow 的新手,所以请指出我可以做些什么来提高我的问题的质量。
所以我的代码所做的(或者更确切地说希望做的)是计算巨大的斐波那契数以一个非常大的 m 为模。为了使算法更高效,我使用了pisano periods。本质上,我计算了 m 的 pisano 周期,然后通过使用以下关系使余数的计算更容易:
第n个斐波那契数的余数(模m)等于第k个斐波那契数的余数(模m) 使得 k = n % p 其中 p 是 pisano 周期m.
为了计算皮萨诺周期,我使用以下属性:
如果当前的Fib % m = 0,并且到目前为止所有Fib的总和 % m = 0,那么当前Fib的索引是pisano周期米。 (注意索引必须大于0)
但是我在这项工作中遇到了一个问题:要计算 pisano 周期,我必须计算连续的斐波那契数。当必须计算的斐波那契数的数量变得非常大(例如 100 000)时,就会出现问题。然后数据类型 long 溢出。
据我所知,任何计算 pisano 周期的努力都需要计算斐波那契,因此唯一的解决方案似乎是将 long 替换为其他东西。如果有人对这个替代品有任何建议,我将不胜感激。
import java.util.*;
public class FibHuge {
public static void main (String [] args) {
Scanner in = new Scanner (System.in);
long num = in.nextLong ();
long mod = in.nextLong();
System.out.println ( getMod(num, mod));
}
private static int getMod (long num, long mod) {
Period per = new Period();
long period = per.getPeriod (mod);
int newFibNum = (int)(num % period);
num = (num % mod);
Integer ia[] = new Integer [per.al.size()];
ia = per.al.toArray (ia);
return ia[newFibNum];
}
}
class Period {
ArrayList <Long> al;
long FNum;
long SNum;
Period () {
al = new ArrayList <Long> ();
FNum = 0;
SNum = 1;
}
private long getFib (long first, long second){
return first + second;
}
long getPeriod (long mod){
boolean bool = true;
long fibcount = 0;
long currentmod = 0;
long fib = 0;
long sum = 0;
while (bool){
if (fibcount <= 1){
currentmod = fibcount % mod;
al.add (currentmod);
sum += fibcount;
}
else {
fib = getFib (FNum, SNum);
FNum = SNum;
SNum = fib;
currentmod = (fib % mod);
al.add (currentmod);
sum += fib;
}
if ( (currentmod == 0 & (sum % mod) == 0) & fibcount > 0){
return fibcount;
}
fibcount++;
}
return mod; //essentially just to satisfy the return condition
}
}
【问题讨论】:
-
当需要计算的斐波那契数变得非常大,比如 100 000 时,就会出现问题。 - 我认为你对斐波那契数有错误的感觉。它们呈指数级快速增长 - 第 93 个斐波那契数超出了多头的范围。
-
@Leon 哦,好吧,这比我想象的要糟糕得多。尽管我知道它们呈指数级增长,但我没想到会这么快就消失了。
标签: java performance math long-integer