1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
pub fn lagrange_interpolation<T>(xs: &[T], ys: &[T], one: T, zero: T) -> Vec<T> where T: Clone + Copy + std::ops::Sub<Output = T> + std::ops::Mul<Output = T> + std::ops::Div<Output = T> + std::ops::AddAssign + std::ops::SubAssign + std::ops::MulAssign, { let n = xs.len(); let mut all_c = vec![zero; n + 1]; all_c[0] = one; for &x in xs.iter() { let mut next = vec![zero; n + 1]; next[1..(n + 1)].clone_from_slice(&all_c[..n]); for j in 0..n { next[j] -= x * all_c[j]; } all_c = next; } let mut c = vec![zero; n]; for i in 0..n { let mut qi = one; for j in 0..n { if i == j { continue; } qi *= xs[i] - xs[j]; } let ri = ys[i] / qi; let mut tmp_c = all_c.clone(); for j in (0..n).rev() { c[j] += ri * tmp_c[j + 1]; let next_c = tmp_c[j + 1] * xs[i]; tmp_c[j] += next_c; } } c } #[cfg(test)] mod tests { use super::*; use crate::math::mod_int::mod_int::{set_mod_int, ModInt}; use rand::{thread_rng, Rng}; const MOD: i64 = 1_000_000_007; #[test] fn test_lagrange_interpolation() { set_mod_int(MOD); let mut rng = thread_rng(); let n = 500; for _ in 0..10 { let mut xs = vec![]; let mut ys = vec![]; for _ in 0..n { xs.push(ModInt::from(rng.gen_range(0, MOD))); ys.push(ModInt::from(rng.gen_range(0, MOD))); } let c = lagrange_interpolation(&xs, &ys, ModInt::from(1), ModInt::from(0)); for i in 0..n { let mut y = ModInt::from(0); let x = xs[i]; for i in 0..n { y += x.pow(i as i64) * c[i]; } assert_eq!(y.value(), ys[i].value()); } } } }