diff --git a/content/numerical/GcdConvolution.h b/content/numerical/GcdConvolution.h new file mode 100644 index 000000000..9c4c94e1b --- /dev/null +++ b/content/numerical/GcdConvolution.h @@ -0,0 +1,26 @@ +/** + * Author: Luke Videckis + * Date: 2024-02-20 + * Source: https://github.com/programming-team-code/programming_team_code/blob/main/convolution/gcd_convolution.hpp + * Description: Returns $\displaystyle c[k] = \sum_{gcd(i,j)=k} a[i] \cdot b[j]$. + * Time: O(n \log n) + * Status: unknown + */ +#pragma once + +const int mod = 998'244'353; +vector gcd_convolution(const vector& a, + const vector& b) { + int n = ssize(a); + vector c(n); + for (int g = n - 1; g >= 1; g--) { + int64_t sum_a = 0, sum_b = 0; + for (int i = g; i < n; i += g) { + sum_a += a[i], sum_b += b[i]; + if ((c[g] -= c[i]) < 0) c[g] += mod; + } + sum_a %= mod, sum_b %= mod; + c[g] = (c[g] + sum_a * sum_b) % mod; + } + return c; +} diff --git a/content/numerical/LcmConvolution.h b/content/numerical/LcmConvolution.h new file mode 100644 index 000000000..3f4ede5f3 --- /dev/null +++ b/content/numerical/LcmConvolution.h @@ -0,0 +1,26 @@ +/** + * Author: Luke Videckis + * Date: 2024-02-20 + * Source: https://github.com/programming-team-code/programming_team_code/blob/main/convolution/lcm_convolution.hpp + * Description: Returns $\displaystyle c[k] = \sum_{lcm(i,j)=k} a[i] \cdot b[j]$. + * Time: O(n \log n) + * Status: unknown + */ +#pragma once + +const int mod = 998'244'353; +vector lcm_convolution(const vector& a, + const vector& b) { + int n = ssize(a); + vector sum_a(n), sum_b(n); + vector c(n); + for (int i = 1; i < n; i++) { + for (int j = i; j < n; j += i) + sum_a[j] += a[i], sum_b[j] += b[i]; + sum_a[i] %= mod, sum_b[i] %= mod; + c[i] = (c[i] + sum_a[i] * sum_b[i]) % mod; + for (int j = i + i; j < n; j += i) + if ((c[j] -= c[i]) < 0) c[j] += mod; + } + return c; +} diff --git a/content/numerical/chapter.tex b/content/numerical/chapter.tex index afefd94cd..1dbc45be1 100644 --- a/content/numerical/chapter.tex +++ b/content/numerical/chapter.tex @@ -31,3 +31,5 @@ \section{Fourier transforms} \kactlimport{FastFourierTransformMod.h} \kactlimport{NumberTheoreticTransform.h} \kactlimport{FastSubsetTransform.h} + \kactlimport{GcdConvolution.h} + \kactlimport{LcmConvolution.h}