#3260
Hard Algorithms Find the largest palindrome divisible by k
Math String Dynamic Programming Greedy Number Theory
16.9% acceptance
Feb 25, 2026
108
70
You are given two positive integers n and k.
Return the largest integer having n digits that is both a palindrome and divisible by k.
Solution
Rust
Time O(n³)
Space O(n)
impl Solution {
pub fn largest_palindrome(n: i32, k: i32) -> String {
let n = n as usize;
let k = k as usize;
// Trivial case: every number is divisible by 1
if k == 1 {
return "9".repeat(n);
}
let h = (n + 1) / 2; // free digits: left half + optional middle
// Precompute 10^i mod k for all i in O(n) instead of O(n²)
let mut pow10 = vec![0usize; n];
pow10[0] = 1 % k;
for i in 1..n {
pow10[i] = (pow10[i - 1] * 10) % k;
}
// Weight of free position i:
// For i < n-1-i (not middle): contributes to positions i and n-1-i → w = (10^(n-1-i) + 10^i) % k
// For i == n-1-i (middle, n odd): w = 10^i % k
let mut ws = vec![0usize; h];
for i in 0..h {
let mirror = n - 1 - i;
if i == mirror {
ws[i] = pow10[i];
} else {
ws[i] = (pow10[i] + pow10[mirror]) % k;
}
}
// reach[i][r] = true iff d[i..h-1] (each 0..9) can sum to r mod k
// k <= 9, so indices 0..k fit in [false; 9]
let mut reach = vec![[false; 9]; h + 1];
reach[h][0] = true;
for i in (0..h).rev() {
for r in 0..k {
for d in 0..10usize {
let dw = (d * ws[i]) % k;
let sub = (k + r - dw) % k;
if reach[i + 1][sub] {
reach[i][r] = true;
break;
}
}
}
}
// Greedy: at each position, try largest digit first
let mut digits = vec![0u8; h];
let mut acc = 0usize; // accumulated sum mod k (d[0..i] contribution)
for i in 0..h {
let needed = (k - acc) % k; // need d[i..h-1] to contribute this mod k
let start_d = if i == 0 { 1usize } else { 0 };
for d in (start_d..=9usize).rev() {
let dw = (d * ws[i]) % k;
let sub_needed = (k + needed - dw) % k;
if reach[i + 1][sub_needed] {
digits[i] = d as u8;
acc = (acc + dw) % k;
break;
}
}
}
// Build palindrome string
// First half (including middle if n odd): digits[0..h]
// Mirror: digits[0..h-1] reversed (excluding middle) for n odd, digits[0..h] reversed for n even
let mirror_len = if n % 2 == 1 { h - 1 } else { h };
let mut result = Vec::with_capacity(n);
result.extend(digits[0..h].iter().map(|&d| b'0' + d));
result.extend(digits[0..mirror_len].iter().rev().map(|&d| b'0' + d));
String::from_utf8(result).unwrap()
}
}