spl

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Forestedf/spl

:heavy_check_mark: poly/fps_log_sparse.hpp

Depends on

Verified with

Code

#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;
}
Back to top page