Skip to content

Commit e30d590

Browse files
committed
feat: Implement logarithm and integration functions for polynomial operations
1 parent 921f0e8 commit e30d590

4 files changed

Lines changed: 96 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/log_of_formal_power_series"
2+
3+
#include "../weilycoder/poly/elementary_func/logarithm.hpp"
4+
#include <iostream>
5+
#include <vector>
6+
using namespace std;
7+
using namespace weilycoder;
8+
9+
int main() {
10+
cin.tie(nullptr)->sync_with_stdio(false);
11+
cin.exceptions(cin.failbit | cin.badbit);
12+
size_t n;
13+
cin >> n;
14+
vector<uint64_t> a(n);
15+
for (size_t i = 0; i < n; ++i)
16+
cin >> a[i];
17+
auto res = ntt_logarithm<998244353>(a, n);
18+
for (size_t i = 0; i < n; ++i)
19+
cout << res[i] << " \n"[i + 1 == n];
20+
return 0;
21+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef WEILYCODER_POLY_ELEMENTARY_FUNC_DERIVATIVE_HPP
2+
#define WEILYCODER_POLY_ELEMENTARY_FUNC_DERIVATIVE_HPP
3+
4+
#include <vector>
5+
6+
namespace weilycoder {
7+
template <typename T, typename MultiplyFunc>
8+
std::vector<T> derivative(const std::vector<T> &poly, MultiplyFunc number_mul) {
9+
if (poly.size() <= 1)
10+
return {};
11+
std::vector<T> res(poly.size() - 1);
12+
for (size_t i = 1; i < poly.size(); ++i)
13+
res[i - 1] = number_mul(poly[i], T(i));
14+
return res;
15+
}
16+
} // namespace weilycoder
17+
18+
#endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef WEILYCODER_POLY_ELEMENTARY_FUNC_INTEGRATE_HPP
2+
#define WEILYCODER_POLY_ELEMENTARY_FUNC_INTEGRATE_HPP
3+
4+
#include "../../number_theory/mod_utility.hpp"
5+
#include <vector>
6+
7+
namespace weilycoder {
8+
template <typename T, typename MultiplyFunc, typename InverseFunc>
9+
std::vector<T> integrate(const std::vector<T> &poly, MultiplyFunc number_mul,
10+
InverseFunc number_inv) {
11+
std::vector<T> res(poly.size() + 1);
12+
for (size_t i = 0; i < poly.size(); ++i)
13+
res[i + 1] = number_mul(poly[i], number_inv(T(i + 1)));
14+
return res;
15+
}
16+
17+
template <uint64_t mod>
18+
std::vector<uint64_t> ntt_poly_integrate(const std::vector<uint64_t> &poly) {
19+
return integrate<>(poly, mod_inv<mod>);
20+
}
21+
} // namespace weilycoder
22+
23+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef WEILYCODER_POLY_ELEMENTARY_FUNC_LOGARITHM_HPP
2+
#define WEILYCODER_POLY_ELEMENTARY_FUNC_LOGARITHM_HPP
3+
4+
#include "../../number_theory/mod_utility.hpp"
5+
#include "../ntt_convolve.hpp"
6+
#include "derivative.hpp"
7+
#include "integrate.hpp"
8+
#include "inverse.hpp"
9+
#include "multiply.hpp"
10+
#include <cstdint>
11+
#include <vector>
12+
13+
namespace weilycoder {
14+
template <typename T, typename PolyMultiplyFunc, typename SubtractFunc,
15+
typename MultiplyFunc, typename InverseFunc>
16+
std::vector<T> logarithm(const std::vector<T> &poly, size_t n,
17+
PolyMultiplyFunc multiply, SubtractFunc number_sub,
18+
MultiplyFunc number_mul, InverseFunc number_inv) {
19+
if (poly.empty() || poly[0] != T(1))
20+
throw std::invalid_argument(
21+
"Logarithm is only defined for polynomials with constant term 1.");
22+
auto inv = poly_inv(poly, n, multiply, number_sub, number_inv);
23+
auto prod = poly_mul(derivative(poly, number_mul), inv, n - 1, multiply);
24+
return integrate(prod, number_mul, number_inv);
25+
}
26+
27+
template <uint64_t mod>
28+
std::vector<uint64_t> ntt_logarithm(const std::vector<uint64_t> &poly, size_t n) {
29+
return logarithm(poly, n, ntt_convolve<mod>, mod_sub<mod>, mod_mul<mod>,
30+
mod_inv<mod>);
31+
}
32+
} // namespace weilycoder
33+
34+
#endif

0 commit comments

Comments
 (0)