Loading

模板

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]);
	}
};
posted @ 2024-03-09 15:24  TongKa  阅读(14)  评论(1编辑  收藏  举报