use crate::{
chinese_remainder_theorem_garner_algorithm_i64::garner,
greatest_common_divisor_euclidean_recurse_i64::gcd,
};
pub fn mod_linear_equation(
mut m: i64,
mut a: i64,
mut b: i64,
) -> Option<i64> {
assert!(m > 0 && a > 0);
let g = gcd(m, a);
if b % g != 0 {
return None;
}
m /= g;
a /= g;
b /= g;
let mut y = garner(&[(m, 0), (a, b)]);
let lcm = m * a;
if y < b {
y += lcm;
}
let x = (y - b) / a;
debug_assert!(0 <= x && x < lcm);
Some(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let cases = vec![
((10, 4, 3), 2),
((1000, 11, 2), -1),
((998244353, 897581057, 595591169), 249561088),
((10000, 6, 14), 3571),
];
for ((n, s, k), ans) in cases {
let ans = if ans == -1 { None } else { Some(ans) };
assert_eq!(mod_linear_equation(n, k, s), ans);
}
}
}