This documentation is automatically generated by online-judge-tools/verification-helper
#include "poly/fps_log_sparse.hpp"
#pragma once
#include <cassert>
#include <utility>
#include <vector>
#include "../number_theory/factorial.hpp"
// O(n * (# of nonzero))
template <typename T>
std::vector<T> fps_log_sparse(const std::vector<T> &f) {
assert(!f.empty() && f[0] == T(1));
int n = (int)f.size();
std::vector<std::pair<int, T>> nonzero;
for (int i = 1; i < n; ++i) {
if (f[i] != T()) {
nonzero.emplace_back(i, f[i]);
}
}
std::vector<T> g = f;
g[0] = T(0);
for (int i = 1; i < n; ++i) {
T sum;
for (auto [j, val] : nonzero) {
if (j > i) {
break;
}
sum += T(i - j) * val * g[i - j];
}
g[i] -= inv<T>(i) * sum;
}
return g;
}
#line 2 "poly/fps_log_sparse.hpp"
#include <cassert>
#include <utility>
#include <vector>
#line 4 "number_theory/factorial.hpp"
template <typename M>
M inv(int n) {
static std::vector<M> data{M::raw(0), M::raw(1)};
static constexpr unsigned MOD = M::get_mod();
assert(0 < n);
while ((int)data.size() <= n) {
unsigned k = (unsigned)data.size();
unsigned r = MOD / k + 1;
data.push_back(M::raw(r) * data[k * r - MOD]);
}
return data[n];
}
template <typename M>
M fact(int n) {
static std::vector<M> data{M::raw(1), M::raw(1)};
assert(0 <= n);
while ((int)data.size() <= n) {
unsigned k = (unsigned)data.size();
data.push_back(M::raw(k) * data.back());
}
return data[n];
}
template <typename M>
M inv_fact(int n) {
static std::vector<M> data{M::raw(1), M::raw(1)};
assert(0 <= n);
while ((int)data.size() <= n) {
unsigned k = (unsigned)data.size();
data.push_back(inv<M>(k) * data.back());
}
return data[n];
}
template <typename M>
M binom(int n, int k) {
assert(0 <= n);
if (k < 0 || n < k) {
return M::raw(0);
}
return fact<M>(n) * inv_fact<M>(k) * inv_fact<M>(n - k);
}
template <typename M>
M n_terms_sum_k(int n, int k) {
assert(0 <= n && 0 <= k);
if (n == 0) {
return (k == 0 ? M::raw(1) : M::raw(0));
}
return binom<M>(n + k - 1, n - 1);
}
#line 6 "poly/fps_log_sparse.hpp"
// O(n * (# of nonzero))
template <typename T>
std::vector<T> fps_log_sparse(const std::vector<T> &f) {
assert(!f.empty() && f[0] == T(1));
int n = (int)f.size();
std::vector<std::pair<int, T>> nonzero;
for (int i = 1; i < n; ++i) {
if (f[i] != T()) {
nonzero.emplace_back(i, f[i]);
}
}
std::vector<T> g = f;
g[0] = T(0);
for (int i = 1; i < n; ++i) {
T sum;
for (auto [j, val] : nonzero) {
if (j > i) {
break;
}
sum += T(i - j) * val * g[i - j];
}
g[i] -= inv<T>(i) * sum;
}
return g;
}