haar_lib/math/combinatorics/
stirling_first_small_p.rs1use crate::math::combinatorics::binomial_coefficient::ExtLucas;
8
9pub struct StirlingFirstSmallP {
11 p: u64,
12 bc: ExtLucas,
13 s: Vec<Vec<u64>>,
14}
15
16impl StirlingFirstSmallP {
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 s[0][0] = 1;
26
27 for i in 1..=p as usize {
28 for j in 1..=i {
29 let mut t = (i as u64 - 1) * s[i - 1][j] % p;
30 if t != 0 {
31 t = p - t;
32 }
33
34 s[i][j] = t + s[i - 1][j - 1];
35 if s[i][j] >= p {
36 s[i][j] %= p;
37 }
38 }
39 }
40
41 Self { p, bc, s }
42 }
43
44 pub fn calc(&self, n: u64, k: u64) -> u64 {
48 let i = n / self.p;
49 let j = n % self.p;
50
51 let mut b = (k - i) % (self.p - 1);
52 if b == 0 && j > 0 {
53 b = self.p - 1;
54 }
55 let a = ((k - i) - b) / (self.p - 1);
56
57 let mut ret = self.bc.calc(i, a) * self.s[j as usize][b as usize] % self.p;
58 if (i - a) % 2 == 1 && ret != 0 {
59 ret = self.p - ret;
60 }
61
62 ret
63 }
64}