Last digit of partial sum of the (n - m) Fibonacci numbers
EasyUpdated: Sep 18, 2025
Problem
Given two integers m and n with 0 ≤ m ≤ n, compute the last digit (units digit) of the partial sum
F(m) + F(m+1) + ... + F(n)
- Input: integers
mandn(either as integers or as decimal strings for very large values). - Output:
S = (F(m) + ... + F(n)) mod 10(a single digit 0–9).
Examples
Example 1
Input: m = 3, n = 7
Output: 1
Explanation: F3+F4+F5+F6+F7 = 2+3+5+8+13 = 31 -> last digit 1
Example 2
Input: m = 10, n = 2000000000000
Output: (computed via Pisano reduction)
Solution
Key identity: the partial sum has a closed form
S(m,n) = F(m) + ... + F(n) = F(n+2) − F(m+1)
Therefore it suffices to compute F(n+2) mod 10 and F(m+1) mod 10, subtract them modulo 10, and return a non-negative digit.
Because F(k) mod 10 is periodic with Pisano period 60, reduce indices modulo 60 before evaluating. Two practical methods follow.
Method 1 — Pisano reduction + iterative Fibonacci (recommended)
Intuition
Reduce the large indices n+2 and m+1 modulo 60 (Pisano period for modulus 10). Then compute the two Fibonacci values by iterating at most 60 steps.
Approach
- Compute
a = (n+2) % 60andb = (m+1) % 60. Ifnormare given as decimal strings, reduce them digit-by-digit:r = (r*10 + d) % 60. - Compute
F(a) mod 10andF(b) mod 10by iterating up to 60 steps withx,y = y, (x+y) % 10. - Return
(F(a) - F(b) + 10) % 10to avoid negative digits.
Edge cases:
- If
m > ntreat as invalid; ifm == nthe result isF(n) % 10.
Code
C++
class Solution {
public:
static int reduce_mod60_str(const std::string &s) {
int r = 0; for (char ch : s) r = (r*10 + (ch - '0')) % 60; return r;
}
static int fib_mod10_by_idx(int k) {
int a = 0, b = 1;
for (int i = 0; i < k; ++i) { int nxt = (a + b) % 10; a = b; b = nxt; }
return a;
}
int partial_sum_last_digit_str(const std::string &ms, const std::string &ns) {
int m = reduce_mod60_str(ms); int n = reduce_mod60_str(ns);
int a = (n + 2) % 60; int b = (m + 1) % 60;
int fa = fib_mod10_by_idx(a); int fb = fib_mod10_by_idx(b);
return (fa - fb + 10) % 10;
}
};
Go
package main
func reduceMod60Str(s string) int { r:=0; for _, ch := range s { r = (r*10 + int(ch-'0')) % 60 }; return r }
func fibMod10ByIdx(k int) int { a,b:=0,1; for i:=0;i<k;i++ { a,b = b, (a+b)%10 }; return a }
func PartialSumLastDigitStr(ms, ns string) int {
m := reduceMod60Str(ms); n := reduceMod60Str(ns)
a := (n+2)%60; b := (m+1)%60
fa := fibMod10ByIdx(a); fb := fibMod10ByIdx(b)
return (fa - fb + 10) % 10
}
Java
class Solution {
private static int reduceMod60Str(String s) {
int r = 0; for (char ch : s.toCharArray()) r = (r*10 + (ch - '0')) % 60; return r;
}
private static int fibMod10ByIdx(int k) {
int a = 0, b = 1; for (int i=0;i<k;++i) { int nxt=(a+b)%10; a=b; b=nxt; } return a;
}
public int partialSumLastDigitStr(String ms, String ns) {
int m = reduceMod60Str(ms), n = reduceMod60Str(ns);
int a = (n + 2) % 60, b = (m + 1) % 60;
int fa = fibMod10ByIdx(a), fb = fibMod10ByIdx(b);
return (fa - fb + 10) % 10;
}
}
Kotlin
object Solution {
private fun reduceMod60Str(s: String): Int { var r=0; for (ch in s) r=(r*10 + (ch - '0')) % 60; return r }
private fun fibMod10ByIdx(k: Int): Int { var a=0; var b=1; repeat(k) { val nxt=(a+b)%10; a=b; b=nxt }; return a }
fun partialSumLastDigitStr(ms: String, ns: String): Int {
val m = reduceMod60Str(ms); val n = reduceMod60Str(ns)
val a = (n + 2) % 60; val b = (m + 1) % 60
return (fibMod10ByIdx(a) - fibMod10ByIdx(b) + 10) % 10
}
}
Python
class Solution:
@staticmethod
def reduce_mod60_str(s: str) -> int:
r = 0
for ch in s:
r = (r*10 + (ord(ch) - 48)) % 60
return r
@staticmethod
def fib_mod10_by_idx(k: int) -> int:
a, b = 0, 1
for _ in range(k):
a, b = b, (a + b) % 10
return a
def partial_sum_last_digit_str(self, ms: str, ns: str) -> int:
m = self.reduce_mod60_str(ms); n = self.reduce_mod60_str(ns)
a = (n + 2) % 60; b = (m + 1) % 60
return (self.fib_mod10_by_idx(a) - self.fib_mod10_by_idx(b) + 10) % 10
def partial_sum_last_digit(self, m: int, n: int) -> int:
return self.partial_sum_last_digit_str(str(m), str(n))
Rust
pub struct Solution;
impl Solution {
fn reduce_mod60_str(s: &str) -> usize { s.bytes().fold(0usize, |r,ch| (r*10 + (ch - b'0') as usize) % 60) }
fn fib_mod10_by_idx(k: usize) -> u8 { let (mut a, mut b) = (0u8, 1u8); for _ in 0..k { let nxt = (a + b) % 10; a = b; b = nxt; } a }
pub fn partial_sum_last_digit_str(ms: &str, ns: &str) -> u8 {
let m = Self::reduce_mod60_str(ms); let n = Self::reduce_mod60_str(ns);
let a = (n + 2) % 60; let b = (m + 1) % 60;
((Self::fib_mod10_by_idx(a) + 10) - Self::fib_mod10_by_idx(b)) % 10
}
}
Complexity
- ⏰ Time complexity:
O(L + P)whereLis the length (in digits) ofmandnwhen given as strings andP = 60(Pisano period for mod 10). Reduction takesO(L)and the iterative Fibonacci steps take at mostO(60). - 🧺 Space complexity:
O(1)extra space.
Method 2 — Pisano reduction + fast-doubling (optional)
Intuition
After reducing indices to k1=(n+2)%60 and k2=(m+1)%60, fast-doubling computes F(k) mod 10 in O(log k) steps. For mod 10 the k are ≤ 60 so this is optional.
Code
def fib_pair(n: int, mod: int):
if n == 0: return (0,1)
a,b = fib_pair(n>>1, mod)
c = (a * ((2*b - a) % mod)) % mod
d = ((a*a) % mod + (b*b) % mod) % mod
if n & 1:
return (d, (c+d) % mod)
else:
return (c, d)
# reduce indices then return (fib_pair(k1,10)[0] - fib_pair(k2,10)[0] + 10) % 10
Complexity
- ⏰ Time complexity:
O(L + log P)whereLis digits of inputs andP=60. - 🧺 Space complexity:
O(log P)recursion depth orO(1)iterative.