模板
BSGS
int BSGS(int a , int b){
int y = sqrt(p) + 1;
gp_hash_table<int , int> mp;
int t = b;
for(int n = 0; n <= y; ++ n , t = Mul(t , a)) mp[t] = n;
int tmp = 1;
for(int i = 1; i <= y; ++ i , tmp = Mul(tmp , a));
t = tmp;
for(int m = 1; m <= y; ++ m , t = Mul(t , tmp)) {
if(mp.find(t) != mp.end()){
return m * y - mp[t];
}
}
return -1;
}
manacher
int d[N << 1];
int manacher(char* s){
int len = strlen(s + 1);
d[1] = 1;
for(int i = 2 , l = 1 , r = 1; i <= len; ++ i){
int j = l + r - i , dj = (j ? d[j] : 0);
d[i] = max(0 , min(dj , j - l + 1));
if(j - dj + 1 <= l){
while(i - d[i] >= 1 && i + d[i] <= len && s[i - d[i]] == s[i + d[i]]){
++ d[i];
}
l = i - d[i] + 1 , r = i + d[i] - 1;
}
}
int res = 1;
for(int i = 1; i <= len; ++ i){
res = max(res , d[i] - 1);
}
return res;
}
ST表
const int N = 1e5 + 5;
const int MB = ceil(log2(N)) + 1;
struct S_T {
int st[50][N] , pw2[50];
void init(int* a , int n){
for(int i = 1; i <= n; ++ i){
st[0][i] = a[i];
}
int lim = __lg(n) + 1;
pw2[0] = 1;
for(int i = 1; i <= lim; ++ i)pw2[i] = pw2[i - 1] * 2;
for(int s = 1; s <= lim; ++ s){
for(int i = 1; i + pw2[s] - 1 <= n; ++ i){
st[s][i] = max(st[s - 1][i] , st[s - 1][i + pw2[s - 1]]);
}
}
}
int qwq(int l , int r){
int LG = __lg(r - l + 1);
return max(st[LG][l] , st[LG][r - pw2[LG] + 1]);
}
}ST;
SA后缀数组
struct S_A {
int sa[N * 2] , rk[N * 2] , rk1[N * 2] , sz = S , sec[N * 2] , cnt[N * 2];
void init(){
for(int i = 1; i <= len; ++ i) rk[i] = c[i] , ++ cnt[c[i]];
for(int i = 1; i <= S; ++ i) cnt[i] += cnt[i - 1];
for(int i = len; i >= 1; -- i) sa[cnt[rk[i]] -- ] = i;
}
void radixsort(){
for(int i = 0; i <= sz; ++ i) cnt[i] = 0;
for(int i = 1; i <= len; ++ i) ++ cnt[rk[i]];
for(int i = 1; i <= sz; ++ i) cnt[i] += cnt[i - 1];
for(int i = len; i >= 1; -- i) sa[cnt[rk[sec[i]]] -- ] = sec[i] , sec[i] = 0;
}
void Sa(){
init();
for(int k = 1; k <= len; k *= 2){
int oo = 0;
for(int i = len - k + 1; i <= len; ++ i) sec[ ++ oo] = i;
for(int i = 1; i <= len; ++ i){
if(sa[i] > k){
sec[ ++ oo] = sa[i] - k;
}
}
radixsort();
for(int i = 1; i <= len; ++ i) rk1[i] = rk[i];
sz = rk[sa[1]] = 1;
for(int i = 2; i <= len; ++ i){
if(rk1[sa[i]] == rk1[sa[i - 1]] &&
rk1[sa[i] + k] == rk1[sa[i - 1] + k]){
rk[sa[i]] = sz;
}
else {
rk[sa[i]] = ++ sz;
}
}
if(sz == len) return ;
}
}
}SA;
DINIC最大流
namespace DINIC {
const int E = ;
const int V = ;
int s = V - 1 , t = V - 2;
struct edge {
int to , nxt;
int flow;
}e[E << 1];
int head[V] , cnt = 1;
void adde(int u , int v , int flow){//directed
e[ ++ cnt] = {v , head[u] , flow};
head[u] = cnt;
e[ ++ cnt] = {u , head[v] , 0};
head[v] = cnt;
}
int dis[V] , now[V];
int bfs(){
memset(dis , 0 , sizeof dis);
queue<int> q;
q.push(s); dis[s] = 1;
while(!q.empty()){
int u = q.front(); q.pop();
now[u] = head[u];
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to , fl = e[i].flow;
if(fl && !dis[v]){
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
return dis[t] != 0;
}
int dfs(int u , int flow){//进入时有多少流量
if(u == t) return flow;
int rst = flow;
for(int i = now[u]; i && rst; i = e[i].nxt){
now[u] = i;
int v = e[i].to; int fl = e[i].flow;
if(fl && dis[v] == dis[u] + 1){
int cur = dfs(v , min(fl , rst));
// if(!cur) dis[v] = 0;
e[i].flow -= cur;
e[i ^ 1].flow += cur;
rst -= cur;
}
}
return flow - rst;//初始减剩下即为delta
}
int Dinic(){
int res = 0;
while(bfs()){
res += dfs(s , INF);
}
return res;
}
};
DINIC费用流
struct DINIC {
int s , t;
struct edge {
int to , nxt;
ll flow , c;
}e[M << 1];
int head[N] , cnt = 1;
void adde(int u , int v , ll flow , ll c){
e[ ++ cnt] = {v , head[u] , flow , c};
head[u] = cnt;
e[ ++ cnt] = {u , head[v] , 0 , -c};
head[v] = cnt;
}
ll dis[N];
int now[N] , mk[N];
queue<int> q;
int bfs(){
memset(dis , 0x3F , sizeof dis);
while(!q.empty()) q.pop();
q.push(s); dis[s] = 0; mk[s] = 1;
while(!q.empty()){
int u = q.front(); q.pop();
mk[u] = 0;
now[u] = head[u];
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to; ll fl = e[i].flow , c = e[i].c;
if(fl && dis[v] > dis[u] + c){
dis[v] = dis[u] + c;
if(mk[v] == 0){
q.push(v); mk[v] = 1;
}
}
}
}
return dis[t] != INFl;
}
ll cost = 0;
ll dfs(int u , ll flow){//进入时有多少流量
if(u == t) return flow;
mk[u] = 1;
ll rst = flow;
for(int i = now[u]; i && rst; i = e[i].nxt){
now[u] = i;
int v = e[i].to; ll c = e[i].c , fl = e[i].flow;
if(mk[v] == 0 && fl && dis[v] == dis[u] + c){
ll cur = dfs(v , min(fl , rst));
// if(!cur) dis[v] = 0;
cost += cur * c;
e[i].flow -= cur;
e[i ^ 1].flow += cur;
rst -= cur;
}
}
mk[u] = 0;
return flow - rst;//初始减剩下即为delta
}
ll Dinic(){
ll res = 0;
while(bfs()){
// for(int i = 1; i <= n; ++ i) now[i] = head[i];
// cout << res << endl;
res += dfs(s , INFl);
}
return res;
}
}D;
多项式清空最高指示:所有要传入NTT等函数的数组,要清空,记得要求出lim再清空
多项式模板
const int N = 1e5 + 5;
const int M = N * 4.5;
const int P = 998'244'353;
const int Gr = 3;
const int Gri = 332'748'118;
const int inv2 = 499'122'177;
int lim , len , r[M];
void bi_rev(int x){
lim = 1 , len = 0;
while(lim < x) lim <<= 1 , ++ len;
r[0] = 0;
for(int i = 0; i < lim; ++ i){
r[i] = (r[i >> 1] >> 1) | ((i & 1) << (len - 1));
}
}
void derive(int *F , int *G , int n){
for(int i = 0; i < n; ++ i){
G[i] = Mul(i + 1 , F[i + 1]);
}
G[n - 1] = 0;
}
int fac[M] , inv[M];
void integral(int *F , int *G , int n){
fac[0] = 1;
for(int i = 1; i <= n; ++ i){
fac[i] = Mul(fac[i - 1] , i);
}
inv[n] = qpow(fac[n] , P - 2);
for(int i = n - 1; i >= 0; -- i){
inv[i] = Mul(inv[i + 1] , i + 1);
inv[i + 1] = Mul(inv[i + 1] , fac[i]);
}
for(int i = 1; i < n; ++ i){
G[i] = Mul(F[i - 1] , inv[i]);
}
G[0] = 0;
}
int g[M];
void NTT(int *F , int op){
for(int i = 0; i < lim; ++ i){
if(i < r[i]) swap(F[i] , F[r[i]]);
}
for(int mid = 1; mid < lim; mid <<= 1){
int gn = qpow(op > 0 ? Gr : Gri , (P - 1) / (mid << 1));
g[0] = 1;
for(int i = 1; i <= mid; ++ i) g[i] = Mul(g[i - 1] , gn);
for(int R = mid << 1 , j = 0; j < lim; j += R){
for(int k = 0; k < mid; ++ k){
int x = F[j + k] , y = Mul(g[k] , F[j + mid + k]);
F[j + k] = Add(x , y);
F[j + mid + k] = Sub(x , y);
}
}
}
if(op == -1){
int lim_inv = qpow(lim , P - 2);
for(int i = 0; i < lim; ++ i){
F[i] = Mul(F[i] , lim_inv);
}
}
}
int tF[M];
void polyinv(int *F , int *G , int t){
if(t == 1){
memset(G , 0 , sizeof G);
G[0] = qpow(F[0] , P - 2);
return ;
}
polyinv(F , G , (t + 1) >> 1);
bi_rev(t + t);
for(int i = (t + 1) >> 1; i < lim; ++ i) G[i] = 0;
for(int i = 0; i < t; ++ i){
tF[i] = F[i];
}
for(int i = t; i < lim; ++ i){
tF[i] = 0;
}
NTT(tF , 1); NTT(G , 1);
for(int i = 0; i < lim; ++ i){
G[i] = Sub(Add(G[i] , G[i]) , Mul(tF[i] , Mul(G[i] , G[i])));
}
NTT(G , -1);
}
int tG[M];
void polysqrt(int *F , int *G , int t){
if(t == 1){
G[0] = 1/*sqrt(F[0])*/;
return ;
}
polysqrt(F , G , (t + 1) >> 1);
bi_rev(t + t - 1);
for(int i = (t + 1) >> 1; i < lim; ++ i) G[i] = 0;
for(int i = 0; i < lim; ++ i) tG[i] = 0;
polyinv(G , tG , t);
bi_rev(t + t - 1);
for(int i = t; i < lim; ++ i) tG[i] = 0;
for(int i = 0; i < t; ++ i) tF[i] = F[i];
for(int i = t; i < lim; ++ i) tF[i] = 0;
NTT(G , 1); NTT(tG , 1); NTT(tF , 1);
for(int i = 0; i < lim; ++ i){
G[i] = Mul(inv2 , Add(G[i] , Mul(tG[i] , tF[i])));
}
NTT(G , -1);
}
void polydiv(int *F , int *G , int *Q , int *R , int n , int m){//deg F = n,deg G = m
reverse(F , F + n + 1);
reverse(G , G + m + 1);
polyinv(G , tG , n - m + 1);
bi_rev(2 * n - m + 1);
for(int i = n - m + 1; i < lim; ++ i) tG[i] = 0;
NTT(F , 1); NTT(tG , 1);
for(int i = 0; i < lim; ++ i){
Q[i] = Mul(F[i] , tG[i]);
}
NTT(Q , -1); NTT(F , -1);
for(int i = n - m + 1; i < lim; ++ i) Q[i] = 0;
reverse(Q , Q + n - m + 1);
reverse(F , F + n + 1);
reverse(G , G + m + 1);
NTT(Q , 1); NTT(F , 1); NTT(G , 1);
for(int i = 0; i < lim; ++ i){
R[i] = Sub(F[i] , Mul(Q[i] , G[i]));
}
NTT(R , -1); NTT(Q , -1); NTT(F , -1); NTT(G , -1);
}
int tA[M] , tB[M];
void polyln(int *F , int *G , int n){//deg F = n - 1
derive(F , tA , n);
polyinv(F , tB , n);
bi_rev(2 * n);
for(int i = n; i < lim; ++ i) tA[i] = tB[i] = 0;
NTT(tA , 1); NTT(tB , 1);
for(int i = 0; i < lim; ++ i){
tA[i] = Mul(tA[i] , tB[i]);
}
NTT(tA , -1);
integral(tA , G , n);
}
int tC[M] , tD[M];
void polyexp(int *F , int *G , int t){
if(t == 1){
G[0] = 1/*exp(F[0])*/;
return ;
}
polyexp(F , G , (t + 1) >> 1);
bi_rev(t * 2 + 1);
for(int i = (t + 1) >> 1; i < lim; ++ i) G[i] = 0;
polyln(G , tC , t);
bi_rev(t * 2 + 1);
for(int i = t; i < lim; ++ i) tC[i] = 0;
for(int i = 0; i < t; ++ i) tD[i] = F[i];
for(int i = t; i < lim; ++ i) tD[i] = 0;
NTT(tC , 1); NTT(tD , 1); NTT(G , 1);
for(int i = 0; i < lim; ++ i){
G[i] = Mul(G[i] , Add(Sub(1 , tC[i]) , tD[i]));
}
NTT(G , -1);
}
杜教筛
ll Du_sieve(int n , ll(*g)(ll,ll) , ll(*h)(ll,ll) , uil& S , ll* s){
if(n <= lim) return s[n];
if(S.find(n) != S.end()) return S[n];
// if(n == 1) return 1;
ll l = 2 , r , res = 0;
while(l <= n){
r = n / (n / l);
res -= Du_sieve(n / l , g , h , S , s) * g(l , r);
l = r + 1;
}
res += h(1 , n);
//res /= g(1 , 1);
return S[n] = res;
};
kosaraju
vector<int> G[N] , rG[N] , t;
int vis[N] , scc[N] , iscc = 0;
void korasaju(){
auto dfs1 = [&] (auto self , int u) -> void {
vis[u] = 1;
for(int v : G[u]){
if(!vis[v]) self(self , v);
}
t.push_back(u);
};
for(int i = 1; i <= n; ++ i){
if(!vis[i]) dfs1(dfs1 , i);
}
auto dfs2 = [&] (auto self , int u) -> void {
for(int v : rG[u]){
if(!scc[v]) scc[v] = scc[u] , self(self , v);
}
};
reverse(all(t));
for(int u : t){
if(!scc[u]) scc[u] = ++ iscc , dfs2(dfs2 , u);
}
}
FastIO
namespace FIO {
inline char gc() {
static char buf[1000000] , *p1 = buf , *p2 = buf;
return (p1 == p2) && (p1 = buf , p2 = buf + fread(buf , 1 , 1000000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
using IO_t = int; inline IO_t read() {
IO_t x = 0; bool flg = 0; char ch = gc();
while(!isdigit(ch)) {
flg |= ch == '-';
ch = gc();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = gc();
}
return flg ? -x : x;
}
char obuf[1000000] , *p2 = obuf;
void refresh(){
fwrite(obuf , 1 , p2 - obuf , stdout) , p2 = obuf;
}
inline void write(IO_t x) {
static int stk[100] , tp = 0;
if(x < 0) *p2 ++ = '-' , x = -x;
while(x) stk[ ++ tp] = x % 10 ^ 48 , x /= 10;
while(tp) *p2 ++ = stk[tp] , tp -- ;
p2 - obuf >= 999990 && (refresh() , 1);
}
}
using FIO::read;
using FIO::write;
using FIO::p2;
实数/modint 高斯消元
template<typename Tp>
struct equation_grp {
Tp a[N][N];
int n , m;
equation_grp () {}
equation_grp (int _n , int _m){
n = _n; m = _m;
for(int i = 1; i <= m; ++ i){
fill(a[i] + 1 , a[i] + n + 2 , 0.0);
}
}
bool gauss_jordan(){
for(int i = 1; i <= n; ++ i){
int pos = i;
for(int j = i; j <= m; ++ j)
if(a[j][i] != 0) {pos = j; break;}
if(a[pos][i] == 0) continue;
swap(a[pos] , a[i]);
for(int j = i + 1; j <= m; ++ j){
Tp t = a[j][i] / a[i][i];
for(int k = i; k <= n + 1; ++ k) a[j][k] -= a[i][k] * t;
}
}
for(int i = 1; i <= n; ++ i) if(a[i][i] == 0) return 0;
a[n][n + 1] /= a[n][n]; a[n][n] = 1;
for(int i = n - 1; i >= 1; -- i){
for(int j = i + 1; j <= n; ++ j){
a[i][n + 1] -= a[j][n + 1] * a[i][j]; a[i][j] = 0;
}
a[i][n + 1] /= a[i][i]; a[i][i] = 1;
}
return 1;
}
};
modint模板(最有性价比的一集)
const int P = 998'244'353;
struct mint {
int v;
mint () {v = 0;}
mint (int _v) {v = _v;}
friend mint operator + (mint x , int y){return x.v + y < P ? x.v + y : x.v + y - P;}
friend mint operator - (mint x , int y){return x.v < y ? x.v + P - y : x.v - y;}
friend mint operator * (mint x , int y){return 1ll * x.v * y % P;}
mint qpow(int y){mint res(1) , t(v); while(y){if(y & 1) res = res * t; t = t * t; y >>= 1;} return res;}
friend mint operator / (mint x , int y){mint t(y); return x * t.qpow(P - 2);}
operator int() {return v;}
friend ostream &operator << (ostream &os , mint &x){return os << x.v , os;}
friend istream &operator >> (istream &is , mint &x){return is >> x.v , is;}
};
Lca(vector)
template<typename Tp , const int N>
struct LcaHelper { // for vector
int dep[N] , st[__lg(N) + 2][N * 2] , idx , dfn[N];
inline int Min (int x , int y) {return dep[x] < dep[y] ? x : y;}
inline int gv(Tp e , true_type) {return e;}
inline int gv(Tp e , false_type) {return e[0];}
void init (vector<Tp>* T , int rt = 1) {
idx = 0;
auto dfs = [&] (auto self , int u , int fa) -> void {
dfn[u] = idx + 1;
for(Tp e : T[u]){ int v = gv(e , is_same<Tp,int>());
if(v == fa) continue;
st[0][ ++ idx] = u;
dep[v] = dep[u] + 1;
self(self , v , u);
}
st[0][ ++ idx] = u;
}; dfs(dfs , rt , 0);
for(int s = 1; (1 << s) <= idx; ++ s){
for(int i = 1; i + (1 << s) - 1 <= idx; ++ i){
st[s][i] = Min(st[s - 1][i] , st[s - 1][i + (1 << (s - 1))]);
}
}
}
LcaHelper () {}
LcaHelper (vector<Tp>* T , int rt = 1) {init(T , rt);}
int Get(int u , int v){
if(dfn[u] > dfn[v]) swap(u , v);
int LG = __lg(dfn[v] - dfn[u] + 1);
return Min(st[LG][dfn[u]] , st[LG][dfn[v] - (1 << LG) + 1]);
}
};