Skip to content

Commit

Permalink
Merge pull request #110 from NyaanNyaan/add_misc
Browse files Browse the repository at this point in the history
add misc
  • Loading branch information
NyaanNyaan authored May 4, 2024
2 parents 1ac45ab + d9f70e7 commit d091038
Show file tree
Hide file tree
Showing 13 changed files with 455 additions and 58 deletions.
9 changes: 6 additions & 3 deletions .verify-helper/timestamps.remote.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@
"verify/verify-aoj-other/aoj-1068.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-1130-DG-bfs.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-1377.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-1613.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-1613.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-aoj-other/aoj-2171-bigrational.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-2171.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-2821.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-aoj-other/aoj-2891-2.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-2891.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-aoj-other/aoj-2945-01bfs.test.cpp": "2024-05-03 23:21:26 +0900",
Expand All @@ -98,6 +99,7 @@
"verify/verify-unit-test/bigint2.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/bigint3.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/bigrational.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/binomial-table.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-unit-test/bitset-find-prev.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/complex-fft.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/composite-exp.test.cpp": "2024-05-03 23:21:26 +0900",
Expand Down Expand Up @@ -142,6 +144,7 @@
"verify/verify-unit-test/multipoint-binomial-sum.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/nimber-to-field.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/nimber.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/ntt-64bit.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-unit-test/orderedmap.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/osak.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-unit-test/p-recursive.test.cpp": "2024-05-03 23:21:26 +0900",
Expand Down Expand Up @@ -300,7 +303,7 @@
"verify/verify-yosupo-graph/yosupo-shortest-path-dijkstra-abstruct.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-graph/yosupo-shortest-path.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-graph/yosupo-strongly-connected-components.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-graph/yosupo-tree-hash.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-graph/yosupo-tree-hash.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-yosupo-graph/yosupo-tree-path-composite-sum.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-graph/yosupo-two-edge-cc.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yosupo-math/yosupo-addition-of-big-integers.test.cpp": "2024-05-03 23:21:26 +0900",
Expand Down Expand Up @@ -459,7 +462,7 @@
"verify/verify-yuki/yuki-1783.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1786.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1787.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1789.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1789.test.cpp": "2024-05-04 15:53:37 +0900",
"verify/verify-yuki/yuki-1875.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1939-2.test.cpp": "2024-05-03 23:21:26 +0900",
"verify/verify-yuki/yuki-1939-sparse-pow.test.cpp": "2024-05-03 23:21:26 +0900",
Expand Down
18 changes: 18 additions & 0 deletions modulo/binomial-table.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <vector>
using namespace std;

template <typename mint>
vector<vector<mint>> binomial_table(int n) {
n += 10;
vector dp(n, vector(n, mint{0}));
dp[0][0] = 1;
for (int i = 0; i + 1 < n; i++) {
for (int j = 0; j <= i; j++) {
dp[i + 1][j + 0] += dp[i][j];
dp[i + 1][j + 1] += dp[i][j];
}
}
return dp;
}
200 changes: 200 additions & 0 deletions ntt/ntt-64bit.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#pragma once

#include <vector>
using namespace std;

#include "../math/primitive-root-ll.hpp"

template <typename mint>
struct NTT_64bit {
unsigned long long mod, pr;
int level;
mint dw[64], dy[64];

void setwy(int k) {
mint w[64], y[64];
w[k - 1] = mint(pr).pow((mod - 1) / (1LL << k));
y[k - 1] = w[k - 1].inverse();
for (int i = k - 2; i > 0; --i)
w[i] = w[i + 1] * w[i + 1], y[i] = y[i + 1] * y[i + 1];
dw[1] = w[1], dy[1] = y[1], dw[2] = w[2], dy[2] = y[2];
for (int i = 3; i < k; ++i) {
dw[i] = dw[i - 1] * y[i - 2] * w[i];
dy[i] = dy[i - 1] * w[i - 2] * y[i];
}
}

NTT_64bit() {
mod = mint::get_mod();
if (mod >= 2) {
pr = primitive_root_ll(mod);
level = __builtin_ctzll(mod - 1);
setwy(level);
}
}

void fft4(vector<mint> &a, int k) {
if ((int)a.size() <= 1) return;
if (k == 1) {
mint a1 = a[1];
a[1] = a[0] - a[1];
a[0] = a[0] + a1;
return;
}
if (k & 1) {
int v = 1 << (k - 1);
for (int j = 0; j < v; ++j) {
mint ajv = a[j + v];
a[j + v] = a[j] - ajv;
a[j] += ajv;
}
}
int u = 1 << (2 + (k & 1));
int v = 1 << (k - 2 - (k & 1));
mint one = mint(1);
mint imag = dw[1];
while (v) {
// jh = 0
{
int j0 = 0;
int j1 = v;
int j2 = j1 + v;
int j3 = j2 + v;
for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
mint t0p2 = t0 + t2, t1p3 = t1 + t3;
mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
a[j0] = t0p2 + t1p3, a[j1] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j3] = t0m2 - t1m3;
}
}
// jh >= 1
mint ww = one, xx = one * dw[2], wx = one;
for (int jh = 4; jh < u;) {
ww = xx * xx, wx = ww * xx;
int j0 = jh * v;
int je = j0 + v;
int j2 = je + v;
for (; j0 < je; ++j0, ++j2) {
mint t0 = a[j0], t1 = a[j0 + v] * xx, t2 = a[j2] * ww,
t3 = a[j2 + v] * wx;
mint t0p2 = t0 + t2, t1p3 = t1 + t3;
mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
a[j0] = t0p2 + t1p3, a[j0 + v] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j2 + v] = t0m2 - t1m3;
}
xx *= dw[__builtin_ctzll((jh += 4))];
}
u <<= 2;
v >>= 2;
}
}

void ifft4(vector<mint> &a, int k) {
if ((int)a.size() <= 1) return;
if (k == 1) {
mint a1 = a[1];
a[1] = a[0] - a[1];
a[0] = a[0] + a1;
return;
}
int u = 1 << (k - 2);
int v = 1;
mint one = mint(1);
mint imag = dy[1];
while (u) {
// jh = 0
{
int j0 = 0;
int j1 = v;
int j2 = v + v;
int j3 = j2 + v;
for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
mint t0p1 = t0 + t1, t2p3 = t2 + t3;
mint t0m1 = t0 - t1, t2m3 = (t2 - t3) * imag;
a[j0] = t0p1 + t2p3, a[j2] = t0p1 - t2p3;
a[j1] = t0m1 + t2m3, a[j3] = t0m1 - t2m3;
}
}
// jh >= 1
mint ww = one, xx = one * dy[2], yy = one;
u <<= 2;
for (int jh = 4; jh < u;) {
ww = xx * xx, yy = xx * imag;
int j0 = jh * v;
int je = j0 + v;
int j2 = je + v;
for (; j0 < je; ++j0, ++j2) {
mint t0 = a[j0], t1 = a[j0 + v], t2 = a[j2], t3 = a[j2 + v];
mint t0p1 = t0 + t1, t2p3 = t2 + t3;
mint t0m1 = (t0 - t1) * xx, t2m3 = (t2 - t3) * yy;
a[j0] = t0p1 + t2p3, a[j2] = (t0p1 - t2p3) * ww;
a[j0 + v] = t0m1 + t2m3, a[j2 + v] = (t0m1 - t2m3) * ww;
}
xx *= dy[__builtin_ctzll(jh += 4)];
}
u >>= 4;
v <<= 2;
}
if (k & 1) {
u = 1 << (k - 1);
for (int j = 0; j < u; ++j) {
mint ajv = a[j] - a[j + u];
a[j] += a[j + u];
a[j + u] = ajv;
}
}
}

void ntt(vector<mint> &a) {
if ((int)a.size() <= 1) return;
fft4(a, __builtin_ctz(a.size()));
}

void intt(vector<mint> &a) {
if ((int)a.size() <= 1) return;
ifft4(a, __builtin_ctz(a.size()));
mint iv = mint(a.size()).inverse();
for (auto &x : a) x *= iv;
}

vector<mint> multiply(const vector<mint> &a, const vector<mint> &b) {
int l = a.size() + b.size() - 1;
if (min<int>(a.size(), b.size()) <= 40) {
vector<mint> s(l);
for (int i = 0; i < (int)a.size(); ++i)
for (int j = 0; j < (int)b.size(); ++j) s[i + j] += a[i] * b[j];
return s;
}
int k = 2, M = 4;
while (M < l) M <<= 1, ++k;
setwy(k);
vector<mint> s(M);
for (int i = 0; i < (int)a.size(); ++i) s[i] = a[i];
fft4(s, k);
if (a.size() == b.size() && a == b) {
for (int i = 0; i < M; ++i) s[i] *= s[i];
} else {
vector<mint> t(M);
for (int i = 0; i < (int)b.size(); ++i) t[i] = b[i];
fft4(t, k);
for (int i = 0; i < M; ++i) s[i] *= t[i];
}
ifft4(s, k);
s.resize(l);
mint invm = mint(M).inverse();
for (int i = 0; i < l; ++i) s[i] *= invm;
return s;
}

void ntt_doubling(vector<mint> &a) {
int M = (int)a.size();
auto b = a;
intt(b);
mint r = 1, zeta = mint(pr).pow((mint::get_mod() - 1) / (M << 1));
for (int i = 0; i < M; i++) b[i] *= r, r *= zeta;
ntt(b);
copy(begin(b), end(b), back_inserter(a));
}
};
39 changes: 39 additions & 0 deletions tree/centroid.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <utility>
#include <vector>
using namespace std;

template <typename G>
vector<int> centroid(const G &g) {
const int N = (int)g.size();

vector<pair<int, int> > st;
st.emplace_back(0, -1);
vector<int> sz(N), par(N);
while (!st.empty()) {
auto p = st.back();
if (sz[p.first] == 0) {
sz[p.first] = 1;
for (auto &to : g[p.first])
if (to != p.second) st.emplace_back(to, p.first);
} else {
for (auto &to : g[p.first])
if (to != p.second) sz[p.first] += sz[to];
par[p.first] = p.second;
st.pop_back();
}
}

vector<int> ret;
int size = N;
for (int i = 0; i < N; i++) {
int val = N - sz[i];
for (auto &to : g[i])
if (to != par[i]) val = max(val, sz[to]);
if (val < size) size = val, ret.clear();
if (val == size) ret.emplace_back(i);
}

return ret;
}
49 changes: 49 additions & 0 deletions tree/rooted-tree-hash.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include <array>
#include <chrono>
#include <random>
#include <vector>
using namespace std;

#include "../internal/internal-hash.hpp"

template <typename G>
struct RootedTreeHash {
using Hash = internal::Hash<1>;

const G& g;
int n;
vector<Hash> hash;
vector<int> depth;

static vector<Hash>& xs() {
static vector<Hash> _xs;
return _xs;
}

RootedTreeHash(const G& _g, int root = 0) : g(_g), n(g.size()) {
hash.resize(n);
depth.resize(n, 0);
while ((int)xs().size() <= n) xs().push_back(Hash::get_basis());
dfs(root, -1);
}

private:
int dfs(int c, int p) {
int dep = 0;
for (auto& d : g[c]) {
if (d != p) dep = max(dep, dfs(d, c) + 1);
}
Hash x = xs()[dep], h = Hash::set(1);
for (auto& d : g[c]) {
if (d != p) h = h * (x + hash[d]);
}
hash[c] = h;
return depth[c] = dep;
}
};

/**
* @brief 根付き木のハッシュ
*/
File renamed without changes.
Loading

0 comments on commit d091038

Please sign in to comment.