The goal is to compute F(n) modulo m (m up to 10 power 5), where n may be really huge: up to 10 power 18.
My algorithm is too slow.
My approach: Calculate and store all Fibonacci numbers up to m, then iterate through that array and apply modulo on the fibonacci's.
Once the length of the pisano period is found, i can use this length to calculate the modulo of any F(n)
My code:
import java.math.BigInteger;
import java.util.*;
public class FibonacciAgain {
private static ArrayList<BigInteger> calc_fib() {
ArrayList<BigInteger> fib = new ArrayList<>();
fib.add(BigInteger.ZERO);
fib.add(BigInteger.ONE);
for (int i = 2; i <= 100000; i++) {
fib.add(fib.get(i - 2).add(fib.get(i - 1)));
}
return fib;
}
private static long calculatePeriod(ArrayList<BigInteger> fib, long modulo) {
long periodLength = 0;
boolean periodFound = false;
long[] period = new long[1000000];
period[0] = 0;
period[1] = 1;
period[2] = 1;
int i = 3;
while (!periodFound) {
//period[i] = fib.get(i)
//period[i]= fib.get(i).divide(new BigInteger(String.valueOf(i))).longValue();
//System.out.println("Fib at " + i + ": " + fib.get(i));
period[i] = fib.get(i).mod(new BigInteger(String.valueOf(modulo))).longValue();
//System.out.println("1:" + period[i]);
//System.out.println("2:" + period[i - 1]);
// System.out.println("3: " + period[i - 2]);
if (i == 100000){
periodFound = true;
periodLength = i - 1;
}
// if (period[i] == 1 && period[i - 1] == 1 && period[i - 2] == 0) {
if (period[i - 1] == 1 && period[i - 2] == 0) {
periodFound = true;
periodLength = i - 2;
//System.out.println("found");
}
i++;
}
//System.out.println("Period Length:" + periodLength);
return periodLength;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
long m = scanner.nextLong();
//M Fibonacci Numbers up to are stored here
ArrayList<BigInteger> fib = new ArrayList<>();
fib = calc_fib();
// get the length of the pisano period
long periodLength = calculatePeriod(fib, m);
//
long fibFirst = n%periodLength;
System.out.println(fib.get((int) fibFirst).mod(new BigInteger(String.valueOf(m))).longValue());
}
}
Any advice, how to make it faster?