Skip to content

Commit 8e0dae1

Browse files
committed
feat: Implement polynomial exponential functions with NTT support
1 parent 1b31031 commit 8e0dae1

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_formal_power_series"
2+
3+
#include "../weilycoder/poly/elementary_func/exponential.hpp"
4+
#include <cstdint>
5+
#include <iostream>
6+
#include <vector>
7+
using namespace std;
8+
using namespace weilycoder;
9+
10+
int main() {
11+
cin.tie(nullptr)->sync_with_stdio(false);
12+
cin.exceptions(cin.failbit | cin.badbit);
13+
size_t n;
14+
cin >> n;
15+
16+
vector<uint64_t> a(n);
17+
for (size_t i = 0; i < n; ++i)
18+
cin >> a[i];
19+
20+
auto res = ntt_exponential<998244353>(a, n);
21+
for (size_t i = 0; i < n; ++i)
22+
cout << res[i] << " \n"[i + 1 == n];
23+
return 0;
24+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#ifndef WEILYCODER_POLY_ELEMENTARY_FUNC_EXPONENTIAL_HPP
2+
#define WEILYCODER_POLY_ELEMENTARY_FUNC_EXPONENTIAL_HPP
3+
4+
/**
5+
* @file exponential.hpp
6+
* @brief Polynomial Exponential Functions
7+
*/
8+
9+
#include "../../number_theory/mod_utility.hpp"
10+
#include "logarithm.hpp"
11+
#include <vector>
12+
13+
namespace weilycoder {
14+
/**
15+
* @brief Compute the exponential of a polynomial modulo x^n.
16+
* @tparam T Coefficient type.
17+
* @tparam PolyMultiplyFunc Type of the multiplication function.
18+
* @tparam AddFunc Type of the addition function for coefficients.
19+
* @tparam SubtractFunc Type of the subtraction function for coefficients.
20+
* @tparam MultiplyFunc Type of the multiplication function for coefficients.
21+
* @tparam InverseFunc Type of the inversion function for coefficients.
22+
* @param poly Coefficients of the polynomial.
23+
* @param n Degree up to which the exponential is computed (result size will be n).
24+
* @param multiply Function to multiply two polynomials.
25+
* @param number_add Function to add two coefficients.
26+
* @param number_sub Function to subtract two coefficients.
27+
* @param number_mul Function to multiply two coefficients.
28+
* @param number_inv Function to compute the multiplicative inverse of a coefficient.
29+
* @return Coefficients of the exponential polynomial.
30+
*/
31+
template <typename T, typename PolyMultiplyFunc, typename AddFunc,
32+
typename SubtractFunc, typename MultiplyFunc, typename InverseFunc>
33+
std::vector<T> exponential(const std::vector<T> &poly, size_t n,
34+
PolyMultiplyFunc multiply, AddFunc number_add,
35+
SubtractFunc number_sub, MultiplyFunc number_mul,
36+
InverseFunc number_inv) {
37+
if (!poly.empty() && poly[0] != T(0))
38+
throw std::invalid_argument(
39+
"Exponential is only defined for polynomials with constant term 0.");
40+
std::vector<T> result = {T(1)};
41+
for (size_t len = 1; len < n; len <<= 1) {
42+
size_t m = std::min(n, len << 1);
43+
auto temp = logarithm(result, m, multiply, number_sub, number_mul, number_inv);
44+
temp.front() = number_sub(T(1), temp.front());
45+
for (size_t i = 1; i < temp.size(); ++i)
46+
temp[i] = number_sub(T(0), temp[i]);
47+
for (size_t i = 0; i < std::min(poly.size(), m); ++i)
48+
temp[i] = number_add(temp[i], poly[i]);
49+
result = poly_mul(result, temp, m, multiply);
50+
}
51+
return result;
52+
}
53+
54+
/**
55+
* @brief Compute the exponential of a polynomial modulo x^n using NTT
56+
* under a given modulus.
57+
* @tparam mod Modulus for NTT.
58+
* @param poly Coefficients of the polynomial.
59+
* @param n Degree up to which the exponential is computed (result size will be n).
60+
* @return Coefficients of the exponential polynomial.
61+
*/
62+
template <uint64_t mod>
63+
std::vector<uint64_t> ntt_exponential(const std::vector<uint64_t> &poly, size_t n) {
64+
return exponential<uint64_t>(poly, n, ntt_convolve<mod>, mod_add<mod>, mod_sub<mod>,
65+
mod_mul<mod>, mod_inv<mod>);
66+
}
67+
} // namespace weilycoder
68+
69+
#endif

0 commit comments

Comments
 (0)