haar_lib/math/combinatorics/
stirling_second_small_p.rs1use crate::math::combinatorics::binomial_coefficient::ExtLucas;
8
9pub struct StirlingSecondSmallP {
11 p: u64,
12 bc: ExtLucas,
13 s: Vec<Vec<u64>>,
14}
15
16impl StirlingSecondSmallP {
17 pub fn new(p: u64) -> Self {
23 let bc = ExtLucas::new(p, 1);
24 let mut s = vec![vec![0; p as usize + 1]; p as usize + 1];
25
26 s[0][0] = 1;
27
28 for (i, si) in s.iter_mut().enumerate().skip(1) {
29 si[1] = 1;
30 si[i] = 1;
31 }
32
33 for i in 3..=p as usize {
34 for j in 2..i {
35 s[i][j] = (s[i - 1][j - 1] + j as u64 * s[i - 1][j] % p) % p;
36 }
37 }
38
39 Self { p, bc, s }
40 }
41
42 pub fn calc(&self, n: u64, k: u64) -> u64 {
46 if n <= self.p && k <= self.p {
47 return self.s[n as usize][k as usize];
48 }
49
50 let i = k / self.p;
51 let j = k % self.p;
52
53 let mut b = (n - i) % (self.p - 1);
54 if b == 0 {
55 b = self.p - 1;
56 }
57 let a = (n - i - b) / (self.p - 1);
58
59 if b == self.p - 1 {
60 self.bc.calc(a, i) * self.s[self.p as usize - 1][j as usize] % self.p
61 + self.bc.calc(a, i - 1) * self.s[0][j as usize] % self.p
62 } else {
63 self.bc.calc(a, i) * self.s[b as usize][j as usize] % self.p
64 }
65 }
66}