Input: n =10, m =2Output: 1Explanation: sequence of F(i) mod 2is periodic with period 3; F(10) mod 2=1
The key observation: the sequence F(i) mod m is periodic for any integer m >= 2. The period (Pisano period) always starts with 0, 1. If we can find the Pisano period P(m), then F(n) mod m = F(n mod P(m)) mod m, so we only need to compute Fibonacci for a much smaller index.
Compute P by iterating F(i) mod m starting from (0,1) and stop when the pair (prev, cur) becomes (0, 1) again; P is the number of steps to that repeat.
If n is too large to fit in native types (given as a decimal string), compute r = n % P by processing digits: r = (r*10 + d) % P for each digit d.
Compute F(r) mod m by iterating r times (since r < P and P ≤ m*m, this is feasible for small m).
classSolution {
public:staticint pisano_period(int m) {
int prev =0, cur =1;
for (int i =0; i < m * m +1; ++i) {
int next = (prev + cur) % m;
prev = cur; cur = next;
if (prev ==0&& cur ==1) return i +1;
}
return m * m;
}
longlongget_fibonacci_huge(unsignedlonglong n, int m) {
if (m ==1) return0;
int p = pisano_period(m);
unsignedlonglong r = n % p;
longlong a =0, b =1;
if (r ==0) return0;
for (unsignedlonglong i =1; i <= r; ++i) {
longlong nxt = (a + b) % m;
a = b; b = nxt;
}
return a % m;
}
};
classSolution {
privatestaticintpisanoPeriod(int m) {
int prev = 0, cur = 1;
for (int i = 0; i < m * m + 1; ++i) {
int next = (prev + cur) % m; prev = cur; cur = next;
if (prev == 0 && cur == 1) return i + 1;
}
return m * m;
}
publiclonggetFibonacciHuge(long n, int m) {
if (m == 1) return 0;
int p = pisanoPeriod(m);
long r = n % p;
long a = 0, b = 1;
if (r == 0) return 0;
for (long i = 1; i <= r; ++i) {
long nxt = (a + b) % m; a = b; b = nxt;
}
return a % m;
}
}
classSolution {
privatefunpisanoPeriod(m: Int): Int {
var prev = 0; var cur = 1for (i in0..(m*m)) {
val next = (prev + cur) % m
prev = cur; cur = next
if (prev ==0&& cur ==1) return i + 1 }
return m*m
}
fungetFibonacciHuge(n: Long, m: Int): Int {
if (m ==1) return0val p = pisanoPeriod(m)
val r = (n % p).toInt()
if (r ==0) return0var a = 0; var b = 1for (i in1..r) {
val nxt = (a + b) % m
a = b; b = nxt
}
return a % m
}
}
classSolution:
defpisano_period(self, m: int) -> int:
prev, cur =0, 1for i in range(0, m * m +1):
prev, cur = cur, (prev + cur) % m
if prev ==0and cur ==1:
return i +1return m * m
defget_fibonacci_huge(self, n: int, m: int) -> int:
if m ==1:
return0 p = self.pisano_period(m)
r = n % p
a, b =0, 1if r ==0:
return0for _ in range(1, r +1):
a, b = b, (a + b) % m
return a % m
defstr_mod(self, s: str, mod: int) -> int:
r =0for ch in s:
r = (r *10+ (ord(ch) - ord('0'))) % mod
return r
pubstructSolution;
impl Solution {
pubfnpisano_period(m: usize) -> usize {
let (mut prev, mut cur) = (0usize, 1usize);
for i in0..(m*m+1) {
let next = (prev + cur) % m;
prev = cur; cur = next;
if prev ==0&& cur ==1 { return i +1 }
}
m*m
}
pubfnget_fibonacci_huge(mut n: u128, m: usize) -> usize {
if m ==1 { return0 }
let p = Self::pisano_period(m);
let r = (n % (p asu128)) asusize;
if r ==0 { return0 }
let (mut a, mut b) = (0usize, 1usize);
for _ in1..=r {
let nxt = (a + b) % m; a = b; b = nxt;
}
a % m
}
}
⏰ Time complexity: O(m^2 + P) where P = P(m) ≤ m^2; detecting Pisano period takes up to O(m^2) steps and computing F(r) takes O(P) in the worst case. For small m (e.g., m < 1000) this is acceptable.
🧺 Space complexity: O(1) extra space (only a few integer variables).
After reducing n modulo the Pisano period P, computing F(r) can be done faster using the fast-doubling method in O(log r) time. Combining both steps yields O(m^2 + log P) time.
classSolutionFD {
public:// returns pair (F(n), F(n+1)) modulo m
static std::pair<longlong,longlong> fib_pair(unsignedlonglong n, int m) {
if (n ==0) return {0, 1};
auto p = fib_pair(n >>1, m);
longlong a = p.first; longlong b = p.second;
longlong c = (a * ((2*b - a + m) % m)) % m; // F(2k)
longlong d = ( (a*a)%m + (b*b)%m ) % m; // F(2k+1)
if ((n &1) ==0) return {c, d};
elsereturn {d, (c + d) % m};
}
};
deffib_pair(n: int, m: int) -> tuple:
if n ==0:
return (0, 1)
a, b = fib_pair(n >>1, m)
c = (a * ((2*b - a) % m)) % m
d = ((a*a) % m + (b*b) % m) % m
if n &1:
return (d, (c + d) % m)
else:
return (c, d)
defget_fib_fast(n: int, m: int) -> int:
return fib_pair(n, m)[0]