1+ //! Functions that calculate $(+, \times)$ convolution.
2+ //!
3+ //! Given two arrays $a_0, a_1, \ldots, a_{N - 1}$ and $a_0, a_1, \ldots, a_{M - 1}$, They calculate the array $c$ of length $N + M - 1$, defined by
4+ //!
5+ //! \\[
6+ //! c_i = \sum_ {j = 0}^i a_j b_{i - j}
7+ //! \\]
8+
19macro_rules! modulus {
210 ( $( $name: ident) ,* ) => {
311 $(
@@ -29,6 +37,50 @@ use std::{
2937 fmt,
3038} ;
3139
40+ /// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
41+ ///
42+ /// Returns a empty `Vec` if `a` or `b` is empty.
43+ ///
44+ /// # Constraints
45+ ///
46+ /// - $2 \leq m \leq 2 \times 10^9$
47+ /// - $m$ is a prime number.
48+ /// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
49+ ///
50+ /// where $m$ is `M::VALUE`.
51+ ///
52+ /// # Complexity
53+ ///
54+ /// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
55+ ///
56+ /// # Example
57+ ///
58+ /// ```
59+ /// use ac_library_rs::ModInt1000000007 as Mint;
60+ /// use proconio::{input, source::once::OnceSource};
61+ ///
62+ /// input! {
63+ /// from OnceSource::from(
64+ /// "3\n\
65+ /// 1 2 3\n\
66+ /// 3\n\
67+ /// -1 -2 -3\n",
68+ /// ),
69+ /// a: [Mint],
70+ /// b: [Mint],
71+ /// }
72+ ///
73+ /// assert_eq!(
74+ /// ac_library_rs::convolution(&a, &b),
75+ /// [
76+ /// Mint::new(-1),
77+ /// Mint::new(-4),
78+ /// Mint::new(-10),
79+ /// Mint::new(-12),
80+ /// Mint::new(-9),
81+ /// ],
82+ /// );
83+ /// ```
3284#[ allow( clippy:: many_single_char_names) ]
3385pub fn convolution < M > ( a : & [ StaticModInt < M > ] , b : & [ StaticModInt < M > ] ) -> Vec < StaticModInt < M > >
3486where
@@ -68,6 +120,52 @@ where
68120 a
69121}
70122
123+ /// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
124+ ///
125+ /// Returns a empty `Vec` if `a` or `b` is empty.
126+ ///
127+ /// # Constraints
128+ ///
129+ /// - $2 \leq m \leq 2 \times 10^9$
130+ /// - $m$ is a prime number.
131+ /// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
132+ ///
133+ /// where $m$ is `M::VALUE`.
134+ ///
135+ /// # Complexity
136+ ///
137+ /// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
138+ ///
139+ /// # Example
140+ ///
141+ /// ```
142+ /// use ac_library_rs::{Mod1000000007 as M, Modulus as _};
143+ /// use proconio::{input, source::once::OnceSource};
144+ ///
145+ /// const M: u32 = M::VALUE;
146+ ///
147+ /// input! {
148+ /// from OnceSource::from(
149+ /// "3\n\
150+ /// 1 2 3\n\
151+ /// 3\n\
152+ /// -1 -2 -3\n",
153+ /// ),
154+ /// a: [i32],
155+ /// b: [i32],
156+ /// }
157+ ///
158+ /// assert_eq!(
159+ /// ac_library_rs::convolution::convolution_raw::<_, M>(&a, &b),
160+ /// [
161+ /// (-1i32).rem_euclid(M as i32),
162+ /// (-4i32).rem_euclid(M as i32),
163+ /// (-10i32).rem_euclid(M as i32),
164+ /// (-12i32).rem_euclid(M as i32),
165+ /// (-9i32).rem_euclid(M as i32),
166+ /// ],
167+ /// );
168+ /// ```
71169pub fn convolution_raw < T , M > ( a : & [ T ] , b : & [ T ] ) -> Vec < T >
72170where
73171 T : RemEuclidU32 + TryFrom < u32 > + Clone ,
@@ -86,6 +184,40 @@ where
86184 . collect ( )
87185}
88186
187+ /// Calculates the $(+, \times)$ convolution in `i64`.
188+ ///
189+ /// Returns a empty `Vec` if `a` or `b` is empty.
190+ ///
191+ /// # Constraints
192+ ///
193+ /// - $|a| + |b| - 1 \leq 2^{24}$
194+ /// - All elements of the result are inside of the range of `i64`
195+ ///
196+ /// # Complexity
197+ ///
198+ /// - $O(n \log n)$ where $n = |a| + |b|$.
199+ ///
200+ /// # Example
201+ ///
202+ /// ```
203+ /// use proconio::{input, source::once::OnceSource};
204+ ///
205+ /// input! {
206+ /// from OnceSource::from(
207+ /// "3\n\
208+ /// 1 2 3\n\
209+ /// 3\n\
210+ /// -1 -2 -3\n",
211+ /// ),
212+ /// a: [i64],
213+ /// b: [i64],
214+ /// }
215+ ///
216+ /// assert_eq!(
217+ /// ac_library_rs::convolution_i64(&a, &b),
218+ /// [-1, -4, -10, -12, -9],
219+ /// );
220+ /// ```
89221#[ allow( clippy:: many_single_char_names) ]
90222pub fn convolution_i64 ( a : & [ i64 ] , b : & [ i64 ] ) -> Vec < i64 > {
91223 const M1 : u64 = 754_974_721 ; // 2^24
0 commit comments