This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/polynomial/multipoint_evaluation.hpp"$N - 1$ 次多項式 $f(x)$ 及び数列 $x _ 0, \dots , x _ {M - 1}$.
評価値 $f(x _ 0), \dots , f(x _ {M - 1})$.
時間計算量 $\mathrm{O}(M \log ^ 2 M + N \log N)$
剰余の定理より $f(a) = f(x) \bmod (x - a)$ であるから $f(x _ 0) \bmod (x - x _ 0), f(x _ 1) \bmod (x - x _ 1), \dots , f(x _ {M - 1}) \bmod (x - x _ {M - 1})$ が求まれば良い.
ここで,次のような各ノードに多項式をもつ根付き 2 分木 (subproduct tree) を構築する. まず,木は $M$ 個の葉ノードをもち,各ノードには $x - x _ 0, x - x _ 1, \dots , x - x _ {M - 1}$ が書かれている. そして,葉以外のノードにはその 2 つの子ノードに書かれた多項式の積が書かれている. subproduct tree は $\mathrm{O}(M \log ^2 M)$ 時間で構築可能である.
次に根の多項式を $f \bmod (x - x _ 0) (x - x _ 1) \dots (x - x _ {M - 1})$ に書き換える. これは $\mathrm{O}((N + M) \log (N + M))$ 時間かかる. また,多項式 $f, g, h$ に対して $(f \bmod g h) \bmod g = f \bmod g$ が成り立つことから,根から葉に逆方向に向かって $f$ をそのノードに書かれた多項式で割った余りを計算できる. これは最初の構築と同様で $\mathrm{O}(M \log ^ 2 M)$ 時間で処理できる.
こうして最終的に葉ノードに書かれた値が求めたかった評価値である.
middle product を利用した高速化
#pragma once
#include <vector>
#include "FormalPowerSeries.hpp"
template <typename T> struct subproduct_tree {
using poly = FormalPowerSeries<T>;
int m;
std::vector<poly> prod;
subproduct_tree(const std::vector<T>& x) : m(x.size()) {
int k = 1;
while (k < m) k <<= 1;
prod.assign(k << 1, {1});
for (int i = 0; i < m; i++) prod[k + i] = {-x[i], 1};
for (int i = k - 1; i > 0; i--) prod[i] = prod[i << 1] * prod[i << 1 | 1];
}
int size() const { return prod.size() >> 1; }
poly mid_prod(const poly& a, const poly& b) const {}
std::vector<T> multipoint_evaluation(poly f) const {
std::vector<poly> rem(size() << 1);
rem[1] = f % prod[1];
for (int i = 2; i < size() + m; i++) rem[i] = rem[i >> 1] % prod[i];
std::vector<T> res(m);
for (int i = 0; i < m; i++) res[i] = (rem[size() + i].empty() ? 0 : rem[size() + i][0]);
return res;
}
};Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus.py", line 187, in bundle
bundler.update(path)
~~~~~~~~~~~~~~^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 401, in update
self.update(self._resolve(pathlib.Path(included), included_from=path))
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 401, in update
self.update(self._resolve(pathlib.Path(included), included_from=path))
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 401, in update
self.update(self._resolve(pathlib.Path(included), included_from=path))
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 260, in _resolve
raise BundleErrorAt(path, -1, "no such header")
onlinejudge_verify.languages.cplusplus_bundle.BundleErrorAt: atcoder/convolution.hpp: line -1: no such header