From 119beb5f4305f4a471918a4d2da453e74dabe87f Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Mon, 19 Oct 2020 05:12:15 +0900 Subject: [PATCH] [WIP] Add document for `convolution` --- src/convolution.rs | 132 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/src/convolution.rs b/src/convolution.rs index 9576e3e..8ac1dd6 100644 --- a/src/convolution.rs +++ b/src/convolution.rs @@ -1,3 +1,11 @@ +//! Functions that calculate $(+, \times)$ convolution. +//! +//! 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 +//! +//! \\[ +//! c_i = \sum_ {j = 0}^i a_j b_{i - j} +//! \\] + macro_rules! modulus { ($($name:ident),*) => { $( @@ -29,6 +37,50 @@ use std::{ fmt, }; +/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$. +/// +/// Returns a empty `Vec` if `a` or `b` is empty. +/// +/// # Constraints +/// +/// - $2 \leq m \leq 2 \times 10^9$ +/// - $m$ is a prime number. +/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$ +/// +/// where $m$ is `M::VALUE`. +/// +/// # Complexity +/// +/// - $O(n \log n + \log m)$ where $n = |a| + |b|$. +/// +/// # Example +/// +/// ``` +/// use ac_library_rs::ModInt1000000007 as Mint; +/// use proconio::{input, source::once::OnceSource}; +/// +/// input! { +/// from OnceSource::from( +/// "3\n\ +/// 1 2 3\n\ +/// 3\n\ +/// -1 -2 -3\n", +/// ), +/// a: [Mint], +/// b: [Mint], +/// } +/// +/// assert_eq!( +/// ac_library_rs::convolution(&a, &b), +/// [ +/// Mint::new(-1), +/// Mint::new(-4), +/// Mint::new(-10), +/// Mint::new(-12), +/// Mint::new(-9), +/// ], +/// ); +/// ``` #[allow(clippy::many_single_char_names)] pub fn convolution(a: &[StaticModInt], b: &[StaticModInt]) -> Vec> where @@ -68,6 +120,52 @@ where a } +/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$. +/// +/// Returns a empty `Vec` if `a` or `b` is empty. +/// +/// # Constraints +/// +/// - $2 \leq m \leq 2 \times 10^9$ +/// - $m$ is a prime number. +/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$ +/// +/// where $m$ is `M::VALUE`. +/// +/// # Complexity +/// +/// - $O(n \log n + \log m)$ where $n = |a| + |b|$. +/// +/// # Example +/// +/// ``` +/// use ac_library_rs::{Mod1000000007 as M, Modulus as _}; +/// use proconio::{input, source::once::OnceSource}; +/// +/// const M: u32 = M::VALUE; +/// +/// input! { +/// from OnceSource::from( +/// "3\n\ +/// 1 2 3\n\ +/// 3\n\ +/// -1 -2 -3\n", +/// ), +/// a: [i32], +/// b: [i32], +/// } +/// +/// assert_eq!( +/// ac_library_rs::convolution::convolution_raw::<_, M>(&a, &b), +/// [ +/// (-1i32).rem_euclid(M as i32), +/// (-4i32).rem_euclid(M as i32), +/// (-10i32).rem_euclid(M as i32), +/// (-12i32).rem_euclid(M as i32), +/// (-9i32).rem_euclid(M as i32), +/// ], +/// ); +/// ``` pub fn convolution_raw(a: &[T], b: &[T]) -> Vec where T: RemEuclidU32 + TryFrom + Clone, @@ -86,6 +184,40 @@ where .collect() } +/// Calculates the $(+, \times)$ convolution in `i64`. +/// +/// Returns a empty `Vec` if `a` or `b` is empty. +/// +/// # Constraints +/// +/// - $|a| + |b| - 1 \leq 2^{24}$ +/// - All elements of the result are inside of the range of `i64` +/// +/// # Complexity +/// +/// - $O(n \log n)$ where $n = |a| + |b|$. +/// +/// # Example +/// +/// ``` +/// use proconio::{input, source::once::OnceSource}; +/// +/// input! { +/// from OnceSource::from( +/// "3\n\ +/// 1 2 3\n\ +/// 3\n\ +/// -1 -2 -3\n", +/// ), +/// a: [i64], +/// b: [i64], +/// } +/// +/// assert_eq!( +/// ac_library_rs::convolution_i64(&a, &b), +/// [-1, -4, -10, -12, -9], +/// ); +/// ``` #[allow(clippy::many_single_char_names)] pub fn convolution_i64(a: &[i64], b: &[i64]) -> Vec { const M1: u64 = 754_974_721; // 2^24