Loading

板子树杈

高精度

Code
const int MAX = 20000, BASE = 10000;
struct Node {
	int number[MAX + 10], sign, length;
	Node() {
		memset(number, 0, sizeof(number));
		sign = 1, length = 0;
	}
	void ClearZero() {
		while(length >= 1 && number[length] == 0) --length;
		if(!length) sign = 1, length = 1;
	}
	void Init(char s[]) {
		int ans = 0, k = 1;
		if(s[1] == '-') sign = -1;
		for(int i = strlen(s + 1); i >= 1 && s[i] != '-'; --i) {
			ans = ans + (s[i] - '0') * k, k *= 10;
			if (k == BASE) number[++length] = ans, k = 1, ans = 0;
		}
		if(ans) number[++length] = ans;
		ClearZero();
	}
	void Read() {
		static char s[MAX + 10];
		scanf("%s", s + 1);
		Init(s);
	}
	void Write() {
		if(sign == -1) printf("-");
		printf("%d", number[length]);
		for(int i = length - 1; i >= 1; --i)
			printf("%04d", number[i]);
		printf("\n");
	}
	void operator = (const int &b) {
		int c = b;
		if(b < 0) sign = -1, c = -b;
		while(c) number[++length] = c % BASE, c /= BASE;
	}
	bool operator < (const Node &b) const {
		if(length != b.length) return length < b.length;
		for(int i = length; i >= 1; --i) if (number[i] != b.number[i])
			return number[i] < b.number[i];
		return 0;
	}
	bool operator > (const Node &b) const {
		return b < (*this);
	}
	bool operator >= (const Node &b) const {
		return !((*this) < b);
	}
	Node operator+(const Node &b) {
		Node c;
		c.length = max(length, b.length) + 1;
		for(int i = 1; i <= max(length, b.length); ++i) {
			c.number[i] += number[i] + b.number[i];
			c.number[i + 1] += c.number[i] / BASE;
			c.number[i] %= BASE;
		}
		c.ClearZero();
		return c;
	}
	Node operator + (const int &b) {
		Node c; c = b;
		return (*this) + c;
	}
	Node operator - (const Node &b) {
		Node c, d;
		c = (*this), d = b;
		if(c < d) swap(c, d), c.sign = -1;
		for(int i = 1; i <= c.length; ++i) {
			c.number[i] -= d.number[i];
			if(c.number[i] < 0) c.number[i + 1]--, c.number[i] += BASE;
		}
		c.ClearZero();
		return c;
	}
	Node operator - (const int &b) {
		Node c; c = b;
		return (*this) - c;
	}
	Node operator * (const Node &b) {
		Node c;
		c.length = length + b.length;
		if(sign * b.sign == -1) c.sign = -1;
		for(int i = 1; i <= length; ++i)
			for(int j = 1; j <= b.length; ++j) {
				c.number[i + j - 1] += number[i] * b.number[j];
				c.number[i + j] += c.number[i + j - 1] / BASE;
				c.number[i + j - 1] %= BASE;
			}
		for(int i = 1; i <= c.length; ++i) if (c.number[i] >= BASE)
			c.number[i + 1] += c.number[i] / BASE, c.number[i] %= BASE;
		c.ClearZero();
		return c;
	}
	Node operator * (const int &b) {
		Node c; c = b;
		return (*this) * c;
	}
	Node operator / (const Node &b) {
		Node c, t, k, d = b;
		c.length = length;
		if(sign * b.sign == -1) c.sign = -1;
		for(int i = length; i >= 1; --i) {
			t = t * BASE + number[i];
			int l = 1, r = BASE, ans = 0;
			while (l <= r) {
				int mid = l + r >> 1;
				k = d * mid;
				if(k > t) r = mid - 1;
				else l = mid + 1, ans = mid;
			}
			c.number[i] = ans;
			t = t - d * ans;
		}
		c.ClearZero();
		return c;
	}
	Node operator / (const int &b) {
		Node c; c = b;
		return (*this) / c;
	}
	Node operator % (const Node &b) {
		Node c; c = b;
		return (*this) - (*this) / c * c;
	}
	Node operator % (const int &b) {
		Node c; c = b;
		return (*this) % c;
	}
};

最大流

Code
const int NN = 3e3 + 10;
const int MM = 6e3 + 10;
const int INF = 1e9;
struct Edge {
	int nxt, v, w;
} G[MM * 2];
int S, T, head[NN], cnt = 1, dep[NN], cur[NN];
void Add(int u, int v, int w) {
	G[++cnt] = {head[u], v, w}, head[u] = cnt;
	G[++cnt] = {head[v], u, 0}, head[v] = cnt;
}
bool Bfs() {
	memset(dep, 0, sizeof(dep));
	memcpy(cur, head, sizeof(cur));
	static int q[NN], h, t;
	q[h = t = 0] = S , dep[S] = 1;
	while(h <= t) {
		int u = q[h++];
		for(int i = head[u]; i; i = G[i].nxt) if(G[i].w && !dep[G[i].v])
			dep[G[i].v] = dep[u] + 1, q[++t] = G[i].v;
	}
	return dep[T];
}
int Dfs(int u = S, int flow = INF) {
	if(u == T) return flow; int rest = flow;
	for(int i = cur[u]; i && rest; i = G[i].nxt) {
		int v = G[i].v, w = G[i].w; cur[u] = i;
		if(w && dep[v] == dep[u] + 1) {
			int sum = Dfs(v, rest < w ? rest : w);
			if(!sum) dep[v] = 0;
			rest -= sum, G[i].w -= sum, G[i ^ 1].w += sum;
		}
	}
	return flow - rest;
}
int Dinic() {
	int ans = 0;
	while(Bfs()) ans += Dfs();
	return ans;
}

费用流

Code
using ll = long long;
const int NN = 5e3 + 10;
const int MM = 1e4 + 10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
struct Edge {
	int nxt, v, w; ll c;
} G[MM * 2];
int S, T, head[NN], cnt = 1, inq[NN], pre[NN];
ll dis[NN];
void Add(int u, int v, int w, int c) {
	G[++cnt] = {head[u], v, w, c}, head[u] = cnt;
	G[++cnt] = {head[v], u, 0, -c}, head[v] = cnt;
}
bool Bfs() {
	memset(dis, 0x3f, sizeof(dis));
	memset(inq, 0, sizeof(inq));
	queue<int> q;
	q.push(S), dis[S] = 0, inq[S] = 1;
	while(!q.empty()) {
		int u = q.front(); q.pop(); inq[u] = 0;
		for(int i = head[u]; i; i = G[i].nxt) if(G[i].w && dis[G[i].v] > dis[u] + G[i].c) {
			dis[G[i].v] = dis[u] + G[i].c, pre[G[i].v] = i;
			if(!inq[G[i].v]) q.push(G[i].v), inq[G[i].v] = 1;
		}
	}
	return dis[T] != INFLL;
}
pair<int, ll> EK() {
	int ans = 0; ll cost = 0;
	while(Bfs()) {
		int now = INF;
		for(int u = T; u != S; u = G[pre[u] ^ 1].v) now = min(now, G[pre[u]].w);
		ans += now;
		for(int u = T; u != S; u = G[pre[u] ^ 1].v) 
			cost += 1ll * G[pre[u]].c * now, G[pre[u]].w -= now, G[pre[u] ^ 1].w += now;
	}
	return {ans, cost};
}

SA

Code
const int N = 1e6 + 10;
int n, sa[N], rk[N], fir[N], sec[N], buk[N], h[N], height[N], st[20][N];
char s[N];
void RadixSort() {
	memset(buk, 0, sizeof(buk));
	for(int i = 1; i <= n; ++i) buk[fir[i]]++;
	for(int i = 1; i < N; ++i) buk[i] += buk[i - 1];
	for(int i = n; i >= 1; --i) sa[buk[fir[sec[i]]]--] = sec[i];
}
void SuffixSort() {
	for(int i = 1; i <= n; ++i) fir[i] = s[i], sec[i] = i;
	RadixSort();
	for(int len = 1; len <= n; len <<= 1) {
		int cnt = 0;
		for(int i = n - len + 1; i <= n; ++i) sec[++cnt] = i;
		for(int i = 1; i <= n; ++i) if(sa[i] > len) sec[++cnt] = sa[i] - len;
		RadixSort(); swap(fir, sec);
		fir[sa[cnt = 1]] = 1;
		for(int i = 2; i <= n; ++i)
			if(sec[sa[i]] == sec[sa[i - 1]] && sec[sa[i] + len] == sec[sa[i - 1] + len])
				fir[sa[i]] = cnt;
			else fir[sa[i]] = ++cnt;
		if(cnt == n) break;
	}
	for(int i = 1; i <= n; ++i) rk[sa[i]] = i;
	for(int i = 1; i <= n; ++i) {
		h[i] = h[i - 1] ? h[i - 1] - 1 : 0;
		int j = sa[rk[i] - 1];
		while(s[i + h[i]] == s[j + h[i]]) ++h[i];
		height[rk[i]] = st[0][rk[i]] = h[i];
	}
	for(int k = 1; 1 << k <= n; ++k)
		for(int i = 1; i + (1 << k) - 1 <= n; ++i)
			st[k][i] = min(st[k - 1][i], st[k - 1][i + (1 << k - 1)]);
}
int LCP(int l, int r) {
	if(l == r) return n - l + 1;
	if((l = rk[l]) > (r = rk[r])) swap(l, r);
	int k = __lg(r - l); return min(st[k][l + 1], st[k][r - (1 << k) + 1]);
}

NTT

Code
using ll = long long;
using Poly = vector<ll>;
const int N = (1 << 21) + 10;
const int MOD = 998244353;
const int G = 3;
const int IG = 332748118;
int pos[N];
ll Pow(ll a, int p = MOD - 2) {
	ll ans = 1;
	for(; p; p >>= 1, a = a * a % MOD)
		if(p & 1) ans = ans * a % MOD;
	return ans;
}
void NTT(Poly &f, int opt) {
	int len = f.size();
	for(int i = 0; i < len; ++i)
		if(i < pos[i]) swap(f[i], f[pos[i]]);
	for(int n = 2; n <= len; n <<= 1) {
		int m = n >> 1;
		ll wn = Pow(opt ? G : IG, (MOD - 1) / n);
		for(int i = 0; i < len; i += n) {
			ll w = 1;
			for(int j = 0; j < m; ++j, w = w * wn % MOD) {
				ll x = f[i + j], y = f[i + j + m] * w % MOD;
				f[i + j] = (x + y) % MOD;
				f[i + j + m] = (x + MOD - y) % MOD;
			}
		}
	}
	ll inv = Pow(len, MOD - 2);
	if(!opt) for(int i = 0; i < len; ++i)
		f[i] = f[i] * inv % MOD;
}
Poly Mul(Poly &f, Poly &g) {
	int len = 1;
	while(len <= f.size() + g.size() - 2) len <<= 1;
	for(int i = 0; i < len; ++i) {
		pos[i] = pos[i >> 1] >> 1;
		if(i & 1) pos[i] |= len >> 1;
	}
	f.resize(len), g.resize(len);
	NTT(f, 1), NTT(g, 1);
	Poly h(len);
	for(int i = 0; i < len; ++i) h[i] = f[i] * g[i] % MOD;
	NTT(h, 0);
	while(!h.back()) h.pop_back();
	return h;
}
posted @ 2024-03-15 20:17  Aria_Math  阅读(60)  评论(1)    收藏  举报