ダブリングを行うライブラリを書きました.自分用のメモです.
できること
その1
$f : [0, N) \to [0, N)$ が与えられた時, $f^{r}(i)$ を,$r \in [0, R]$ と $i \in [0, N)$ に対して計算する.
典型的には:
- $N$ は $10^5$ くらい,$R$ は $10^{18}$ くらい,または
- $N$ も $R$ も $10^5$ くらいだが,何回も (たとえば $10^5$回くらい) 計算する
その2
上の $f$ の他に,モノイド $(M, \oplus)$ と $m: [0, N) \to M$ が与えられて, $r, i$ に対して $\bigoplus_{k = 0}^{r} m(f^{k}(i))$ を計算する.
使用例
その1
ll R = 100000, N = 100000;
auto f = [&](ll i) -> ll { return i * i % N; };
DoublingFRel d(R, N, f);
ll r = 12345, i = 54321;
cout << d.val(r, i) << endl; // f^{r}(i)
内部テーブルには,$f^{r}(i)$ が,$i \in [0, N)$ と $r = 1, 2, 4, 8, \ldots$ に対して 格納されている.
その2
struct M {
ll v;
M(ll v_ = LLONG_MIN) v(v_) {}
M operator+(const M& o) const { return M(max(v, o.v)); }
};
ll R = 100000, N = 100000;
auto f = [&](ll i) -> ll { return i * i % N; };
auto m = [&](ll i) -> M { return M(i * i * i); };
DoublingFRel d1(R, N, f);
DoublingCum<M> d2(d1, m);
ll r = 12345, i = 54321;
cout << d2.val(r, i); // \sum { m( f^{(j)}(i) ) | j = 0, 1, ..., r-1 }
内部テーブルには, $m( f^{r}(i) )$ が,$i \in [0, N)$ と $r = 1, 2, 4, 8, \ldots$ に対して格納されている.
普通の和を計算するのなら,struct M を定義する必要はない.
ただし,DoublingCum<ll>
のように,テンプレートパラメタを明示的に
与える必要がある.
keywords: doubling