基本
缺省源
#include <bits/stdc++.h>
#define mp std::make_pair
#define pb push_back
#define fi first
#define se second
#define gc getchar
#define pc putchar
#define ep emplace
#define eb emplace_back
#define ctz __builtin_ctz
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef std::pair <int, int> pii;
typedef std::pair <int, ll> pil;
typedef std::pair <ll, int> pli;
typedef std::pair <ll, ll> pll;
int read() {
char c = gc(); int ans = 0; bool flag = true;
while (!isdigit(c)) flag &= (c != '-'), c = gc();
while (isdigit(c)) ans = ans * 10 + c - '0', c = gc();
return flag ? ans : -ans;
}
void Write(int x) {
if (x < 0) pc('-'), x = -x;
if (x < 10) pc(x + '0');
else Write(x / 10), pc(x % 10 + '0');
}
int min(int x, int y) {return x < y ? x : y;}
int max(int x, int y) {return x > y ? x : y;}
void _min(int &x, int y) {if (x > y) x = y;}
void _max(int &x, int y) {if (x < y) x = y;}
超快读入/输出
namespace io {
const int SIZE = (1 << 21) + 1;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1;
inline char getc() {return (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS++)) : *iS++);}
inline void flush() {fwrite(obuf, 1, oS - obuf, stdout); oS = obuf;}
inline void putc(char x) {*oS++ = x; if (oS == oT) flush();}
template <class T>
inline void read(T &x) {
char ch = getc(); bool flag = false; x = 0;
while (!isdigit(ch)) flag |= (ch == '-'), ch = getc();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getc();
if (flag) x = -x;
}
template <class T, class ...Args>
inline void read(T &x, Args&... args) {read(x); read(args...);}
template <class T>
inline void write(T x) {
static char stk[128]; int top = 0;
if(x == 0) {putc('0'); return;}
if(x < 0) putc('-'), x = -x;
while (x) stk[top++] = x % 10, x /= 10;
while (top) putc(stk[--top] + '0');
}
template <class T, class ...Args>
inline void write(T x, Args... args) {write(x); putc(' '); write(args...);}
inline void space() {putc(' ');}
inline void endl() {putc('
');}
struct _flush {~_flush() {flush();}} __flush;
}
using io::read; using io::write; using io::space; using io::endl; using io::getc; using io::putc;
模大质数常用函数
int plus(int x, int y) {return (x += y) >= mod ? x - mod : x;}
int minus(int x, int y) {return (x -= y) < 0 ? x + mod : x;}
void _plus(int &x, int y) {if ((x += y) >= mod) x -= mod;}
void _minus(int &x, int y) {if ((x -= y) < 0) x += mod;}
ll sqr(int x) {return (ll)x * x % mod;}
ll power(ll x, int y, ll ans = 1) {
for (; y; y >>= 1, x = x * x % mod)
if (y & 1) ans = ans * x % mod;
return ans;
}
ll _inv(int x) {return x == 1 ? 1 : (mod - mod / x) * _inv(mod % x) % mod;}
void init_fac(int n) {
for (int i = fac[0] = 1; i <= n; i++) fac[i] = fac[i - 1] * i % mod;
fac_inv[n] = _inv(fac[n]);
for (int i = n; i; i--) fac_inv[i - 1] = fac_inv[i] * i % mod;
}
ll binom(int x, int y) {return x < y || y < 0 ? 0 : fac[x] * fac_inv[y] % mod * fac_inv[x - y] % mod;}
网络流
最大流
namespace maxflow {
const int max_N = ?, max_E = ?, INF = 2e9;
int nxt[2 * max_E], head[max_N], to[2 * max_E], cap[2 * max_E], tot;
int dist[max_N], _head[max_N], n, S, T;
void init(int _n, int _S, int _T) {
n = _n, S = _S, T = _T, tot = 1;
std::fill(head + 1, head + n + 1, 0);
}
void add_edge(int u, int v, int w) {
nxt[++tot] = head[u], head[u] = tot, to[tot] = v, cap[tot] = w;
nxt[++tot] = head[v], head[v] = tot, to[tot] = u, cap[tot] = 0;
}
bool BFS() {
std::fill(dist + 1, dist + n + 1, INF);
std::queue <int> Q; Q.push(S); dist[S] = 0;
while (!Q.empty()) {
int cur = Q.front(); Q.pop();
for (int i = head[cur]; i; i = nxt[i])
if (cap[i] > 0 && dist[to[i]] == INF)
dist[to[i]] = dist[cur] + 1, Q.push(to[i]);
}
return dist[T] < INF;
}
int dfs(int x, int low) {
if (x == T) return low; int used = 0, tmp;
for (int &i = _head[x]; i; i = nxt[i])
if (cap[i] > 0 && dist[to[i]] == dist[x] + 1) {
tmp = dfs(to[i], min(low - used, cap[i]));
if (tmp > 0) used += tmp, cap[i] -= tmp, cap[i ^ 1] += tmp;
if (used == low) break;
}
return used;
}
int solve() {
int ans = 0;
while (BFS()) std::copy(head + 1, head + n + 1, _head + 1), ans += dfs(S, INF);
return ans;
}
}
最小费用最大流
namespace costflow {
const int max_N = ?, max_M = ?, INF = 2e9;
int nxt[2 * max_M], head[max_N], to[2 * max_M], cap[2 * max_M], cost[2 * max_M], dist[max_N], _head[max_N];
int n, S, T, tot, maxflow, mincost;
bool inq[max_N], vis[max_N];
void init(int _n, int _S, int _T) {
n = _n, S = _S, T = _T, tot = 1;
std::fill(head + 1, head + n + 1, 0);
}
void add_edge(int u, int v, int w, int _cost) {
nxt[++tot] = head[u], head[u] = tot, to[tot] = v, cap[tot] = w, cost[tot] = _cost;
nxt[++tot] = head[v], head[v] = tot, to[tot] = u, cap[tot] = 0, cost[tot] = -_cost;
}
bool SPFA() {
std::fill(dist + 1, dist + n + 1, INF);
std::queue <int> Q; Q.push(T); dist[T] = 0, inq[T] = true;
while (!Q.empty()) {
int cur = Q.front(); Q.pop(); inq[cur] = false;
for (int i = head[cur]; i; i = nxt[i])
if (cap[i ^ 1] > 0 && dist[to[i]] > dist[cur] - cost[i]) {
dist[to[i]] = dist[cur] - cost[i];
if (!inq[to[i]]) Q.push(to[i]), inq[to[i]] = true;
}
}
return dist[S] < INF;
}
int dfs(int x, int low) {
if (x == T) return low; vis[x] = true; int used = 0, tmp;
for (int &i = _head[x]; i; i = nxt[i])
if (cap[i] > 0 && dist[to[i]] == dist[x] - cost[i] && !vis[to[i]]) {
tmp = dfs(to[i], min(low - used, cap[i]));
if (tmp > 0) cap[i] -= tmp, cap[i ^ 1] += tmp, used += tmp, mincost += tmp * cost[i];
if (used == low) break;
}
return used;
}
void solve() {
maxflow = mincost = 0;
while (SPFA())
std::copy(head + 1, head + n + 1, _head + 1),
std::fill(vis + 1, vis + n + 1, false), maxflow += dfs(S, INF);
}
}
有源汇有上下界最大流
namespace bounded_maxflow {
int n, S, T, deg[maxflow::max_N];
void init(int _n, int _S, int _T) {
n = _n, S = _S, T = _T;
maxflow::init(n + 2, n + 1, n + 2);
}
void add_edge(int u, int v, int l, int r) {
deg[u] -= l, deg[v] += l, maxflow::add_edge(u, v, r - l);
}
int solve() {
int sum = 0;
for (int i = 1; i <= n; i++)
if (deg[i] > 0) maxflow::add_edge(n + 1, i, deg[i]), sum += deg[i];
else if (deg[i] < 0) maxflow::add_edge(i, n + 2, -deg[i]);
maxflow::add_edge(T, S, maxflow::INF);
if (maxflow::solve() != sum) return -1;
for (int i = 1; i <= n; i++)
for (int j = maxflow::head[i]; j; j = maxflow::nxt[j])
if (maxflow::to[j] > n) maxflow::cap[j] = maxflow::cap[j ^ 1] = 0;
return maxflow::S = S, maxflow::T = T, maxflow::solve();
}
}
字符串
exKMP
namespace exKMP {
const int max_N = ?;
char A[max_N];
int nxt[max_N], extend[max_N];
void get_nxt(char *s, int n) {
std::memcpy(A + 1, s + 1, n); A[n + 1] = 0; nxt[1] = n;
nxt[2] = std::mismatch(A + 2, A + n + 1, A + 1).fi - (A + 2);
for (int i = 3, tmp = 2; i <= n; i++) {
nxt[i] = max(0, min(nxt[i - tmp + 1], nxt[tmp] + tmp - i));
nxt[i] = std::mismatch(A + i + nxt[i], A + n + 1, A + nxt[i] + 1).fi - (A + i);
if (i + nxt[i] > tmp + nxt[tmp]) tmp = i;
}
}
void get_extend(char *B, int m) {
extend[1] = std::mismatch(A + 1, A + n + 1, B + 1).fi - (A + 1);
for (int i = 2, tmp = 1; i <= m; i++) {
extend[i] = max(0, min(nxt[i - tmp + 1], tmp + extend[tmp] - i));
extend[i] = std::mismatch(B + i + extend[i], B + m + 1, A + extend[i] + 1).fi - (B + i);
if (i + extend[i] > tmp + extend[tmp]) tmp = i;
}
}
}
数据结构
并查集
namespace DSU {
int fa[max_N];
void init(int n) {std::iota(fa + 1, fa + n + 1, 1);}
int anc(int x) {return fa[x] == x ? x : fa[x] = anc(fa[x]);}
void link(int x, int y) {fa[anc(x)] = anc(y);}
bool connected(int x, int y) {return anc(x) == anc(y);}
int num() {
int ans = 0;
for (int i = 1; i <= n; i++) ans += (fa[i] == i);
return ans;
}
}
线性代数
拟阵交
namespace matriod_cross {
const int max_N = ?, INF = 2e9;
bool flag[max_N];
std::vector <int> G[max_N];
int n, pre[max_N], dist[max_N];
namespace matriod_1 {
void build() {?}
bool ins(int x) {?}
}
namespace matriod_2 {
void build() {?}
bool ins(int x) {?}
}
bool find_path() {
for (int i = 1; i <= n + 2; i++) G[i].clear();
matriod_1::build(), matriod_2::build();
for (int i = 1; i <= n; i++) {
if (flag[i]) continue; bool tmp = true;
if (matriod_1::ins(i)) G[n + 1].pb(i); else tmp = false;
if (matriod_2::ins(i)) G[i].pb(n + 2); else tmp = false;
if (tmp) return flag[i] = true;
}
for (int i = 1; i <= n; i++) {
if (!flag[i]) continue; flag[i] = false;
matriod_1::build(), matriod_2::build();
for (int j = 1; j <= n; j++) {
if (i == j || flag[j]) continue;
if (matriod_1::ins(j)) G[i].pb(j);
if (matriod_2::ins(j)) G[j].pb(i);
}
flag[i] = true;
}
std::fill(dist + 1, dist + n + 3, INF);
std::queue <int> Q; Q.push(n + 1); dist[n + 1] = 0;
while (!Q.empty()) {
int cur = Q.front(); Q.pop();
for (auto i : G[cur]) if (dist[i] == INF)
dist[i] = dist[cur] + 1, pre[i] = cur, Q.push(i);
}
if (dist[n + 2] == INF) return false;
for (int i = pre[n + 2]; i != n + 1; i = pre[i]) flag[i] ^= 1;
return true;
}
int solve(int _n) {
n = _n; while (find_path());
return std::accumulate(flag + 1, flag + n + 1, 0);
}
}