高精度
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;
}