Repository: atcoder/live_library Branch: master Commit: 63a4f8f78f52 Files: 24 Total size: 20.3 KB Directory structure: gitextract_qzgqkrf0/ ├── README.md ├── aho.cpp ├── bit.cpp ├── cart.cpp ├── cc.cpp ├── cht.cpp ├── comb.cpp ├── extgcd.cpp ├── fps.cpp ├── gcd.cpp ├── geom/ │ ├── circle.cpp │ ├── line.cpp │ └── vector.cpp ├── geom.cpp ├── lca.cpp ├── mat.cpp ├── mint.cpp ├── mp.cpp ├── perm.cpp ├── prime.cpp ├── rerooting.cpp ├── template.cpp ├── uf.cpp └── z.cpp ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ AtCoder解説放送ライブラリ集 ---- ## これは何? [解説放送](https://www.youtube.com/channel/UCtG3StnbhxHxXfE6Q4cPZwQ)で作ったライブラリを公開しています。 ## 目次 ### ユーティリティ |名前|コード|説明| |:--|:--|:--| |テンプレート|[template.cpp](template.cpp)|| |ModInt|[mint.cpp](mint.cpp)|自動でmodを取ってくれる整数型| |座標圧縮|[cc.cpp](cc.cpp)|座標に昇順に番号を振る| |順列|[perm.cpp](perm.cpp)|置換の合成や逆元等| ### データ構造 |名前|コード|説明| |:--|:--|:--| |BIT|[bit.cpp](bit.cpp)|Binary Indexed Tree (Fenwick Tree)| |UnionFind|[uf.cpp](uf.cpp)|Union Find (DSU)| |CHT|[cht.cpp](cht.cpp)|Convex Hull Trick| |CartesianTree|[cart.cpp](cart.cpp)|Cartesian Tree| ### 数学 |名前|コード|説明| |:--|:--|:--| |GCD/LCM|[gcd.cpp](gcd.cpp)|最大公約数と最小公倍数| |extgcd|[extgcd.cpp](extgcd.cpp)|Ai+Bj=gcd(A,B)なるi,jを求める| |Combination|[comb.cpp](comb.cpp)|nCkをmod素数で求める| |Matrix|[mat.cpp](mat.cpp)|行列| |素数|[prime.cpp](prime.cpp)|素数列挙と素因数分解| |FPS|[fps.cpp](fps.cpp)|形式的べき級数| ### グラフ |名前|コード|説明| |:--|:--|:--| |LCA|[lca.cpp](lca.cpp)|最小共通祖先| |全方位木DP|[rerooting.cpp](rerooting.cpp)|全方位木DP| ### 文字列 |名前|コード|説明| |:--|:--|:--| |KMP|[mp.cpp](mp.cpp)|文字列検索アルゴリズム(正確にはMP)| |Z|[z.cpp](z.cpp)|Z-algorithm| |Aho-Corasick|[aho.cpp](aho.cpp)|文字列集合へのマッチを検出する| ### 幾何 |名前|コード|説明| |:--|:--|:--| |基本|[geom.cpp](geom.cpp)|幾何のベース+目次| |Vector|[geom/vector.cpp](geom/vector.cpp)|ベクトル(点を扱う際にも使う)| |Line|[geom/line.cpp](geom/line.cpp)|直線・線分| |Circle|[geom/circle.cpp](geom/circle.cpp)|円| ================================================ FILE: aho.cpp ================================================ // Aho-Corasick // https://youtu.be/BYoRvdgI5EU?t=9633 struct Aho { using MP = unordered_map; vector to; vector cnt, fail; Aho(): to(1), cnt(1) {} int add(const string& s) { int v = 0; for (char c : s) { if (!to[v].count(c)) { to[v][c] = to.size(); to.push_back(MP()); cnt.push_back(0); } v = to[v][c]; } cnt[v]++; return v; } void init() { fail = vector(to.size(), -1); queue q; q.push(0); while (!q.empty()) { int v = q.front(); q.pop(); for (auto [c,u] : to[v]) { fail[u] = (*this)(fail[v],c); cnt[u] += cnt[fail[u]]; q.push(u); } } } int operator()(int v, char c) const { while (v != -1) { auto it = to[v].find(c); if (it != to[v].end()) return it->second; v = fail[v]; } return 0; } int operator[](int v) const { return cnt[v];} }; ================================================ FILE: bit.cpp ================================================ // Binary Indexed Tree (Fenwick Tree) // https://youtu.be/lyHk98daDJo?t=7960 template struct BIT { int n; vector d; BIT(int n=0):n(n),d(n+1) {} void add(int i, T x=1) { for (i++; i <= n; i += i&-i) { d[i] += x; } } T sum(int i) { T x = 0; for (i++; i; i -= i&-i) { x += d[i]; } return x; } T sum(int l, int r) { return sum(r-1) - sum(l-1); } }; ================================================ FILE: cart.cpp ================================================ // Cartesian Tree // https://youtu.be/XVu8-ZnuOiA?t=9291 template struct CartesianTree { int n, root; vector l, r; CartesianTree() {} CartesianTree(const vector& a, bool _max=true) { n = a.size(); l = r = vector(n,-1); vector st; rep(i,n) { int p = -1; while (st.size() && !((a[st.back()] < a[i])^_max)) { int j = st.back(); st.pop_back(); r[j] = p; p = j; } l[i] = p; st.push_back(i); } rep(i,st.size()-1) r[st[i]] = st[i+1]; root = st[0]; } }; ================================================ FILE: cc.cpp ================================================ // Coodinate Compression // https://youtu.be/fR3W5IcBGLQ?t=8550 template struct CC { bool initialized; vector xs; CC(): initialized(false) {} void add(T x) { xs.push_back(x);} void init() { sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(),xs.end()),xs.end()); initialized = true; } int operator()(T x) { if (!initialized) init(); return upper_bound(xs.begin(), xs.end(), x) - xs.begin() - 1; } T operator[](int i) { if (!initialized) init(); return xs[i]; } int size() { if (!initialized) init(); return xs.size(); } }; ================================================ FILE: cht.cpp ================================================ // Convex Hull Trick (max) // https://youtu.be/TSvXG35mmRE?t=7853 struct CHT { struct Linear { ll a, b; Linear(ll a=0, ll b=0): a(a), b(b) {} ll operator()(ll x) const { return a*x+b;} }; deque ls; void add(ll a, ll b) { Linear l(a,b); assert(ls.size() == 0 || ls.back().a <= l.a); while (ls.size() >= 2) { const Linear& l1 = ls[ls.size()-2]; const Linear& l2 = ls.back(); if ((l.a-l2.a)*(l1.b-l2.b) < (l2.a-l1.a)*(l2.b-l.b)) break; ls.pop_back(); } ls.push_back(l); } ll operator()(ll x) { // x: asc ll res = ls[0](x); while (ls.size() >= 2) { ll now = ls[1](x); if (now < res) break; res = now; ls.pop_front(); } return res; } }; ================================================ FILE: comb.cpp ================================================ // combination mod prime // https://youtu.be/8uowVvQ_-Mo?t=6002 // https://youtu.be/Tgd_zLfRZOQ?t=9928 struct modinv { int n; vector d; modinv(): n(2), d({0,1}) {} mint operator()(int i) { while (n <= i) d.push_back(-d[mint::mod()%n]*(mint::mod()/n)), ++n; return d[i]; } mint operator[](int i) const { return d[i];} } invs; struct modfact { int n; vector d; modfact(): n(2), d({1,1}) {} mint operator()(int i) { while (n <= i) d.push_back(d.back()*n), ++n; return d[i]; } mint operator[](int i) const { return d[i];} } facts; struct modfactinv { int n; vector d; modfactinv(): n(2), d({1,1}) {} mint operator()(int i) { while (n <= i) d.push_back(d.back()*invs(n)), ++n; return d[i]; } mint operator[](int i) const { return d[i];} } ifacts; mint comb(int n, int k) { if (n < k || k < 0) return 0; return facts(n)*ifacts(k)*ifacts(n-k); } ================================================ FILE: extgcd.cpp ================================================ // ai+bj=g // https://youtu.be/fDJpXN2R75A?t=6895 ll extgcd(ll a, ll b, ll& i, ll& j) { if (b == 0) { i = 1; j = 0; return a;} ll p = a/b, g = extgcd(b,a-b*p,j,i); j -= p*i; return g; } ================================================ FILE: fps.cpp ================================================ // Formal Power Series using vm = vector; struct fps : vm { #define d (*this) #define s int(vm::size()) template fps(Args...args): vm(args...) {} fps(initializer_list a): vm(a.begin(),a.end()) {} void rsz(int n) { if (s < n) resize(n);} fps& low_(int n) { resize(n); return d;} fps low(int n) const { return fps(d).low_(n);} mint& operator[](int i) { rsz(i+1); return vm::operator[](i);} mint operator[](int i) const { return i= 0; --i) r = r*x+d[i]; return r; } fps operator-() const { fps r(d); rep(i,s) r[i] = -r[i]; return r;} fps& operator+=(const fps& a) { rsz(a.size()); rep(i,a.size()) d[i] += a[i]; return d;} fps& operator-=(const fps& a) { rsz(a.size()); rep(i,a.size()) d[i] -= a[i]; return d;} fps& operator*=(const fps& a) { return d = convolution(d, a);} fps& operator*=(mint a) { rep(i,s) d[i] *= a; return d;} fps& operator/=(mint a) { rep(i,s) d[i] /= a; return d;} fps operator+(const fps& a) const { return fps(d) += a;} fps operator-(const fps& a) const { return fps(d) -= a;} fps operator*(const fps& a) const { return fps(d) *= a;} fps operator*(mint a) const { return fps(d) *= a;} fps operator/(mint a) const { return fps(d) /= a;} fps operator~() const { fps r({d[0].inv()}); for (int i = 1; i < s; i <<= 1) r = r*mint(2) - (r*r*low(i<<1)).low(i<<1); return r.low_(s); } fps& operator/=(const fps& a) { int w = s; d *= ~a; return d.low_(w);} fps operator/(const fps& a) const { return fps(d) /= a;} fps integ() const { fps r; rep(i,s) r[i+1] = d[i]/(i+1); return r; } #undef s #undef d }; ostream& operator<<(ostream&o,const fps&a) { rep(i,a.size()) o<<(i?" ":"")< crossPoint(const Circle& c) { V v = c.o-o; double l = v.norm(); if (equal(l, 0)) return {}; if (equal(l+r+c.r, max({l,r,c.r})*2)) { if (equal(l+r,c.r)) return {o - v*(r/l)}; return {o + v*(r/l)}; } if (l+r+c.r < max({l,r,c.r})*2) return {}; double x = (l*l + r*r - c.r*c.r) / (2*l); double y = sqrt(r*r - x*x); V mid = o + v*(x/l); v = v.rotate90(); return {mid + v*(y/l), mid - v*(y/l)}; } bool isInside(const V& p) const { return (p-o).norm() < r+eps; } }; ================================================ FILE: geom/line.cpp ================================================ struct Line { V s, t; Line(V s=V(0,0), V t=V(0,0)):s(s),t(t){} V dir() const { return t-s;} V normalize() const { return dir().normalize();} double norm() const { return dir().norm();} /* +1: s-t,s-p : ccw * -1: s-t,s-p : cw * +2: t-s-p * -2: s-t-p * 0: s-p-t */ int ccw(const V& p) const { if (dir().cross(p-s) > eps) return +1; if (dir().cross(p-s) < -eps) return -1; if (dir().dot(p-s) < -eps) return +2; if (dir().dot(t-p) < -eps) return -2; return 0; } bool touch(const Line& l) const { int a = ccw(l.s)*ccw(l.t), b = l.ccw(s)*l.ccw(t); return !a || !b || (a == -1 && b == -1); } }; ================================================ FILE: geom/vector.cpp ================================================ // Vector // https://youtu.be/UWbGRhF3Ozw?t=9564 struct V { double x, y; V(double x=0, double y=0): x(x), y(y) {} V& operator+=(const V& v) { x += v.x; y += v.y; return *this;} V operator+(const V& v) const { return V(*this) += v;} V& operator-=(const V& v) { x -= v.x; y -= v.y; return *this;} V operator-(const V& v) const { return V(*this) -= v;} V& operator*=(double s) { x *= s; y *= s; return *this;} V operator*(double s) const { return V(*this) *= s;} V& operator/=(double s) { x /= s; y /= s; return *this;} V operator/(double s) const { return V(*this) /= s;} double dot(const V& v) const { return x*v.x + y*v.y;} double cross(const V& v) const { return x*v.y - v.x*y;} double norm2() const { return x*x + y*y;} double norm() const { return sqrt(norm2());} V normalize() const { return *this/norm();} V rotate90() const { return V(y, -x);} int ort() const { // orthant if (abs(x) < eps && abs(y) < eps) return 0; if (y > 0) return x>0 ? 1 : 2; else return x>0 ? 4 : 3; } bool operator<(const V& v) const { int o = ort(), vo = v.ort(); if (o != vo) return o < vo; return cross(v) > 0; } }; istream& operator>>(istream& is, V& v) { is >> v.x >> v.y; return is; } ostream& operator<<(ostream& os, const V& v) { os<<"("< // T: type of cost struct lca { int n, root, l; vector> to; vector> co; vector dep; vector costs; vector> par; lca(int n):n(n),to(n),co(n),dep(n),costs(n) { l = 0; while ((1<>(n+1,vector(l,n)); } void addEdge(int a, int b, T c=0) { to[a].push_back(b); co[a].push_back(c); to[b].push_back(a); co[b].push_back(c); } void dfs(int v, int d=0, T c=0, int p=-1) { if (p != -1) par[v][0] = p; dep[v] = d; costs[v] = c; for (int i = 0; i < to[v].size(); ++i) { int u = to[v][i]; if (u == p) continue; dfs(u, d+1, c+co[v][i], v); } } void init(int _root=0) { root = _root; dfs(root); for (int i = 0; i < l-1; ++i) { for (int v = 0; v < n; ++v) { par[v][i+1] = par[par[v][i]][i]; } } } // LCA int up(int v, int k) { for (int i = l-1; i >= 0; --i) { int len = 1<= len) k -= len, v = par[v][i]; } return v; } int operator()(int a, int b) { if (dep[a] > dep[b]) swap(a,b); b = up(b, dep[b]-dep[a]); if (a == b) return a; for (int i = l-1; i >= 0; --i) { int na = par[a][i], nb = par[b][i]; if (na != nb) a = na, b = nb; } return par[a][0]; } int length(int a, int b) { int c = (*this)(a,b); return dep[a]+dep[b]-dep[c]*2; } T dist(int a, int b) { int c = (*this)(a,b); return costs[a]+costs[b]-costs[c]*2; } }; ================================================ FILE: mat.cpp ================================================ // https://youtu.be/ylWYSurx10A?t=2352 template struct Matrix { int h, w; vector> d; Matrix() {} Matrix(int h, int w, T val=0): h(h), w(w), d(h, vector(w,val)) {} Matrix& unit() { assert(h == w); rep(i,h) d[i][i] = 1; return *this; } const vector& operator[](int i) const { return d[i];} vector& operator[](int i) { return d[i];} Matrix operator*(const Matrix& a) const { assert(w == a.h); Matrix r(h, a.w); rep(i,h)rep(k,w)rep(j,a.w) { r[i][j] += d[i][k]*a[k][j]; } return r; } Matrix pow(long long t) const { assert(h == w); if (!t) return Matrix(h,h).unit(); if (t == 1) return *this; Matrix r = pow(t>>1); r = r*r; if (t&1) r = r*(*this); return r; } // https://youtu.be/-j02o6__jgs?t=11273 /* mint only mint det() { assert(h == w); mint res = 1; rep(k,h) { for (int i = k; i < h; ++i) { if (d[i][k] == 0) continue; if (i != k) { swap(d[i],d[k]); res = -res; } } if (d[k][k] == 0) return 0; res *= d[k][k]; mint inv = mint(1)/d[k][k]; rep(j,h) d[k][j] *= inv; for (int i = k+1; i < h; ++i) { mint c = d[i][k]; for (int j = k; j < h; ++j) d[i][j] -= d[k][j]*c; } } return res; } //*/ }; ================================================ FILE: mint.cpp ================================================ // auto mod int // https://youtu.be/L8grWxBlIZ4?t=9858 // https://youtu.be/ERZuLAxZffQ?t=4807 : optimize // https://youtu.be/8uowVvQ_-Mo?t=1329 : division const int mod = 1000000007; const int mod = 998244353; struct mint { ll x; // typedef long long ll; mint(ll x=0):x((x%mod+mod)%mod){} mint operator-() const { return mint(-x);} mint& operator+=(const mint a) { if ((x += a.x) >= mod) x -= mod; return *this; } mint& operator-=(const mint a) { if ((x += mod-a.x) >= mod) x -= mod; return *this; } mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;} mint operator+(const mint a) const { return mint(*this) += a;} mint operator-(const mint a) const { return mint(*this) -= a;} mint operator*(const mint a) const { return mint(*this) *= a;} mint pow(ll t) const { if (!t) return 1; mint a = pow(t>>1); a *= a; if (t&1) a *= *this; return a; } // for prime mod mint inv() const { return pow(mod-2);} mint& operator/=(const mint a) { return *this *= a.inv();} mint operator/(const mint a) const { return mint(*this) /= a;} }; istream& operator>>(istream& is, mint& a) { return is >> a.x;} ostream& operator<<(ostream& os, const mint& a) { return os << a.x;} ================================================ FILE: mp.cpp ================================================ // Morris-Pratt // https://youtu.be/9MphwmIsO7Q?t=7283 template struct MP { int n; T t; vector a; MP() {} MP(const T& t): t(t) { n = t.size(); a = vector(n+1); a[0] = -1; int j = -1; for (int i = 0; i < n; ++i) { while (j != -1 && t[j] != t[i]) j = a[j]; j++; a[i+1] = j; } } int operator[](int i) { return a[i];} vector findAll(const T& s) { vector res; int j = 0; for (int i = 0; i < s.size(); ++i) { while (j != -1 && t[j] != s[i]) j = a[j]; j++; if (j == n) { res.push_back(i-j+1); j = a[j]; } } return res; } }; ================================================ FILE: perm.cpp ================================================ // Permutation // https://youtu.be/-j02o6__jgs?t=7302 struct Perm : vector { #define n (int)(size()) #define p (*this) Perm(int _n): vector(_n) { iota(begin(), end(), 0); } template Perm(Args...args): vector(args...) {} Perm(initializer_list a): vector(a.begin(),a.end()) {} Perm operator+(const Perm& a) const { Perm r(n); for (int i = 0; i < n; ++i) r[i] = p[a[i]]; return r; } Perm& operator+=(const Perm& a) { return *this = (*this)+a; } Perm operator-() const { Perm r(n); for (int i = 0; i < n; ++i) r[p[i]] = i; return r; } Perm operator-(const Perm& a) const { return *this + -a; } Perm& operator-=(const Perm& a) { return *this += -a; } // next permutation bool operator++() { return next_permutation(begin(),end()); } #undef n #undef p }; ================================================ FILE: prime.cpp ================================================ // Sieve of Eratosthenes // https://youtu.be/UTVg7wzMWQc?t=2774 struct Sieve { int n; vector f, primes; Sieve(int n=1):n(n), f(n+1) { f[0] = f[1] = -1; for (ll i = 2; i <= n; ++i) { if (f[i]) continue; primes.push_back(i); f[i] = i; for (ll j = i*i; j <= n; j += i) { if (!f[j]) f[j] = i; } } } bool isPrime(int x) { return f[x] == x;} vector factorList(int x) { vector res; while (x != 1) { res.push_back(f[x]); x /= f[x]; } return res; } vector

factor(int x) { vector fl = factorList(x); if (fl.size() == 0) return {}; vector

res(1, P(fl[0], 0)); for (int p : fl) { if (res.back().first == p) { res.back().second++; } else { res.emplace_back(p, 1); } } return res; } vector> factor(ll x) { vector> res; for (int p : primes) { int y = 0; while (x%p == 0) x /= p, ++y; if (y != 0) res.emplace_back(p,y); } if (x != 1) res.emplace_back(x,1); return res; } }; ================================================ FILE: rerooting.cpp ================================================ // Rerooting // https://youtu.be/zG1L4vYuGrg?t=7092 // TODO: vertex info, edge info struct Rerooting { struct DP { DP() {} DP operator+(const DP& a) const { // edit here } DP addRoot() const { // edit here } }; int n; vector> to; vector> dp; vector ans; Rerooting(int n=0):n(n),to(n),dp(n),ans(n) {} void addEdge(int a, int b) { to[a].push_back(b); to[b].push_back(a); } void init() { dfs(0); bfs(0); } DP dfs(int v, int p=-1) { DP dpSum; dp[v] = vector(to[v].size()); rep(i,to[v].size()) { int u = to[v][i]; if (u == p) continue; dp[v][i] = dfs(u,v); dpSum = dpSum + dp[v][i]; } return dpSum.addRoot(); } void bfs(int v, const DP& dpP=DP(), int p=-1) { int deg = to[v].size(); rep(i,deg) if (to[v][i] == p) dp[v][i] = dpP; vector dpSumL(deg+1); rep(i,deg) dpSumL[i+1] = dpSumL[i] + dp[v][i]; vector dpSumR(deg+1); for (int i = deg-1; i >= 0; --i) dpSumR[i] = dpSumR[i+1] + dp[v][i]; ans[v] = dpSumL[deg].addRoot(); rep(i,deg) { int u = to[v][i]; if (u == p) continue; DP d = dpSumL[i] + dpSumR[i+1]; bfs(u, d.addRoot(), v); } } }; ================================================ FILE: template.cpp ================================================ #include using namespace std; #include using namespace atcoder; #define rep(i,n) for (int i = 0; i < (n); ++i) using ll = long long; using P = pair; int main() { return 0; } ================================================ FILE: uf.cpp ================================================ // UnionFind // coding: https://youtu.be/TdR816rqc3s?t=726 // comment: https://youtu.be/TdR816rqc3s?t=6822 struct UnionFind { vector d; UnionFind(int n=0): d(n,-1) {} int find(int x) { if (d[x] < 0) return x; return d[x] = find(d[x]); } bool unite(int x, int y) { x = find(x); y = find(y); if (x == y) return false; if (d[x] > d[y]) swap(x,y); d[x] += d[y]; d[y] = x; return true; } bool same(int x, int y) { return find(x) == find(y);} int size(int x) { return -d[find(x)];} }; ================================================ FILE: z.cpp ================================================ // Z-algorithm // https://snuke.hatenablog.com/entry/2014/12/03/214243 // https://youtu.be/Uqtxz1KTKOQ?t=9214 struct Z { int n; string s; vector z; Z() {} Z(const string& s): s(s) { init();} void init() { n = s.size(); z = vector(n); z[0] = n; for (int i = 1, j = 0; i < n;) { while (i+j < n && s[i+j] == s[j]) ++j; z[i] = j; if (j) { int k = 1; while (i+k < n && k+z[k] < j) { z[i+k] = z[k]; k++; } i += k; j -= k; } else i++; } } int operator[](int i) const { return z[i];} };