函数库

快速读入

int read(){
    int s = 0, f = 0;
    char ch = getchar();
    while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
    while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
    return f ? -s : s;
}

自定义输出

void print(__int128 x){
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

\(\gcd\)

int Get_Gcd(int x, int y) { return y ? Get_Gcd(y, x % y) : x; }

exgcd

int Exgcd(int a, int b, int &x, int &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }
    int Gcd = Exgcd(b, a % b, x, y);
    int t = x;
    x = y, y = t - a / b * y;
    return Gcd;
}

手写队列

struct sdeque{
    int b[maxn << 1], *a = b + maxn;
    int tail = 0, head = 1;
    sdeque() {}
    bool empty() { return tail + 1 == head;}
    int size() { return tail - head + 1; }
    void push_back(int x) { a[++tail] = x; }
    void push_front(int x) { a[--head] = x; }
    void pop_back() { --tail; }
    void pop_front() { ++head; }
    int back() { return a[tail]; }
    int front() { return a[head]; }
}q;

高精加&乘(已封装)

// 压位高精 zhx 亲授
const int Base = 10000;
struct Bignum {
    int len, a[MAXN];
    Bignum () { len = 0, memset(a, 0, sizeof a); }
    Bignum operator + (const Bignum &b) {
        Bignum res;
        res.len = max(len, b.len);
        for(int i = 0; i <= res.len; ++i) {
            res.a[i] += a[i] + b.a[i];
            res.a[i + 1] += res.a[i] / Base;
            res.a[i] %= Base;
        }
        if(res.a[res.len + 1]) ++ res.len;
        return res;
    }
    Bignum operator - (const Bignum &b) {
        Bignum res;
        return res;
    }    
    Bignum operator * (const Bignum &b) {
        Bignum res; // a[0] ye you shu de xie fa
        res.len = len + b.len + 1;
        for(int i = 0; i <= len; ++i) {
            for(int j = 0; j <= b.len; ++j) {
                res.a[i + j] += a[i] * b.a[j];
                res.a[i + j + 1] += res.a[i + j] / Base;
                res.a[i + j] %= Base;
            }
        }
        while(res.len && !res.a[res.len]) res.len --;
        return res;
    }
    void Print() {
        printf("%d", a[len]);
        for(int i = len - 1; i >= 0; --i) printf("%04d", a[i]);
        puts("");
    }
    void Input() {
        char s[MAXN];
        cin >> s;
        int now_ = strlen(s);
        len = (now_ - 1) / 4;
        for(int i = 0, j = now_ - 4; i < len; ++i, j -= 4) {
            // fang fa 1
//            int ans = 0;
//            for(int k = 0; k < 4; ++k) ans = ans * 10 + s[j + k] - '0';
            // fang fa 2
            sscanf(s + j, "%d", &a[i]);
            s[j] = '\0';
            // fang fa 3: atoi
        }
        sscanf(s, "%d", &a[len]);
    }
};
struct Bignum{
    int a[MAXN], len;
    Bignum () { memset(a, 0, sizeof a), len = 0; }
	Bignum operator + (const char s[]) const {
		Bignum t;
		int len2 = strlen(s + 1);
		for(int i = 1; i <= len2; ++i) {
			t.a[i] += a[i] + s[len2 - i + 1] - '0';
			t.a[i + 1] += t.a[i] / 10;
			t.a[i] %= 10;
		}
		for(int i = len2 + 1; i <= len; ++i) t.a[i] += a[i], t.a[i + 1] += t.a[i] / 10, t.a[i] %= 10;
		len2 = max(len, len2);
		if(t.a[len2 + 1]) ++len2;
		t.len = len2;
		return t;
	}
    Bignum operator * (const char s[]) const {
        Bignum t;
        int len2 = strlen(s + 1);
        if(!len) { for(int i = 1; i <= len2; ++i) t.a[i] = s[len2 - i + 1] - '0'; }
        for(int i = 1; i <= len; ++i) 
            for(int j = 1; j <= len2; ++j) 
                t.a[i + j - 1] += a[i] * (s[len2 - j + 1] - '0'),
                t.a[i + j] += t.a[i + j - 1] / 10,
                t.a[i + j - 1] %= 10;
        len2 = len + len2;
        while(!t.a[len2] && len2 > 1) len2--;
        t.len = len2;
        return t;
    }
};

树状数组

namespace Bit {
    int sum[MAXN];
    int lowbit(int x) { return x & -x; }
    void Modify(int x, int val) { for( ; x <= Cnt; x += lowbit(x)) sum[x] += val; }
    int Query(int x) { int res = 0; for( ; x; x -= lowbit(x)) res += sum[x]; return res; }
}
using namespace Bit;

树剖求LCA(已封装)

namespace Cut{
    struct edge{
        int to, nxt;
    }e[MAXN << 1];
    int head[MAXN], num_edge = 0;
    void add_edge(int from, int to) { e[++num_edge] = (edge){to, head[from]}, head[from] = num_edge; }
    void dfs(int u, int fa) {
        dep[u] = dep[fa] + 1, fath[u] = fa, siz[u] = 1;
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(v == fa) continue;
            dfs(v, u);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    void dfs2(int u, int tp) {
        dfn[u] = ++ cnt, pre[cnt] = u, top[u] = tp;
        if(son[u]) dfs2(son[u], tp);
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(v == fath[u] || v == son[u]) continue;
            dfs2(v, v);
        }
    }
    int Get_Lca(int x, int y) {
        while(top[x] != top[y]) dep[top[x]] < dep[top[y]] ? y = fath[top[y]] : x = fath[top[x]];
        return dep[x] < dep[y] ? x : y;
    }
}

线性筛素数(欧拉筛)

int prim[MAXN], Cnt = 0;
bool vis[MAXN];
void Init(int limit) {
    for(int i = 2; i <= limit; ++i) {
        if(!vis[i]) prim[++ Cnt] = i;
        for(int j = 1; j <= Cnt && i * prim[j] <= limit; ++j) {
            vis[i * prim[j]] = true;
            if(i % prim[j] == 0) break;
        }
    }
}
namespace LCT {
    #define f fa[now_]
    #define ls son[now_][0]
    #define rs son[now_][1]
    int fa[MAXN], son[MAXN][2];
    LL siz[MAXN];
    bool tag[MAXN];
    void Push_up(int now_) {
        if(!now_) return ;
        siz[now_] = siz[ls] + siz[rs] + 1;
    }
    void Push_Reverse(int now_) {
        if(!now_) return ;
        swap(ls, rs);
        tag[now_] ^= 1;
    }
    void Push_down(int now_) {
        if(tag[now_]) Push_Reverse(ls), Push_Reverse(rs);
        tag[now_] = 0;
    }
    bool IsRoot(int now_) { return son[f][0] != now_ && son[f][1] != now_; }
    bool Whichson(int now_) { return son[f][1] == now_; }
    void Rotate(int now_) {
        int fa_ = f, w = Whichson(now_);
        if(!IsRoot(f)) son[fa[f]][Whichson(f)] = now_;
        fa[now_] = fa[f];
        
        son[fa_][w] = son[now_][w ^ 1];
        fa[son[fa_][w]] = fa_;
        
        son[now_][w ^ 1] = fa_;
        fa[fa_] = now_;
        Push_up(fa_), Push_up(now_);
    }
    void Update(int now_) {
        if(!IsRoot(now_)) Update(f);
        Push_down(now_);
    }
    void Splay(int now_) {
        Update(now_);
        for( ; !IsRoot(now_); Rotate(now_)) {
            if(!IsRoot(f)) Rotate(Whichson(f) == Whichson(now_) ? f : now_);
        }
    }
    void Access(int now_) {
        for(int pre_ = 0; now_; pre_ = now_, now_ = f) {
            Splay(now_), rs = pre_;
            Push_up(now_);
        }
    }
    void MakeRoot(int now_) { Access(now_), Splay(now_), Push_Reverse(now_); }
    int Find(int now_) {
        Access(now_), Splay(now_);
        while(ls) Push_down(now_), now_ = ls;
        Splay(now_);
        return now_;
    }
    void Split(int x_, int y_) { MakeRoot(x_), Access(y_), Splay(y_); } 
    void Link(int x_, int y_) {
        MakeRoot(x_);
        if(Find(y_) != x_) fa[x_] = y_;
    }
    void Cut(int x_, int y_) {
        MakeRoot(x_);
        if(Find(y_) != x_ || fa[y_] != x_ || son[y_][0]) return ;
        fa[y_] = son[x_][1] = 0;
        Push_up(x_);
    }
    int Query(int x_, int y_) {
        Split(x_, y_);
        return siz[y_];
    }
}

矩阵乘法/快速幂

struct Matrix {
    int a[MAXN][MAXN];
    Matrix() { memset(a, 0, sizeof a); }
    Matrix operator + (const Matrix &b) const {
        Matrix res;
        for(int i = 1; i <= size; ++i) 
            for(int j = 1; j <= size; ++j) 
                res.a[i][j] = a[i][j] + b.a[i][j];
        return res;
    }
    Matrix operator - (const Matrix &b) const {
        Matrix res;
        for(int i = 1; i <= size; ++i) 
            for(int j = 1; j <= size; ++j) 
                res.a[i][j] = a[i][j] - b.a[i][j];
        return res;
    }
    Matrix operator * (const Matrix &b) const {
        Matrix res;
        for(int k = 1; k <= size; ++k) {
            for(int i = 1; i <= size; ++i) {
                for(int j = 1; j <= size; ++j) {
                    res.a[i][j] += a[i][k] * b.a[k][j];
                }
            }
        }
        return res;
    } 
    Matrix operator ^ (const LL x) const{
        Matrix res, base;
        for(int i = 1; i <= size; ++i) res.a[i][i] = 1;//初始化res矩阵
        for(int i = 1; i <= size; ++i) 
            for(int j = 1; j <= size; ++j)
                base.a[i][j] = a[i][j] % mod;
        while(x) {
            if(x & 1) res = res * base;
            base = base * base;
            x >>= 1;
        }
        return res;
    }
};

网络流-最大流

bool bfs(){
    memset(dis, -1, sizeof dis);
    queue<int> q;
    q.push(s);
    dis[s] = 0, cur[s] = head[s];
    while(!q.empty()){
        int u = q.front(); q.pop();
        for(int i = head[u]; i; i = e[i].nxt){
            int v = e[i].to;
            if(dis[v] == -1 && e[i].w){
                q.push(v);
                cur[v] = head[v]; 
                dis[v] = dis[u] + 1;
                if(v == t) return true;
            }
        }
    }
    return false;
}

int dfs(int u, int limit){//多路增广 
    if(u == t) return limit;
    int flow = 0;
    for(int i = cur[u]; i && flow < limit; i = e[i].nxt){//第二个条件是 流量用要够用 
        cur[u] = i;//当前弧优化,保证每条边只增广一次
        int v = e[i].to;
        if(e[i].w && dis[v] == dis[u] + 1){//如果还有残量并且v点在下一层中 
            int f = dfs(v, min(e[i].w, limit - flow));//向下传递的流量是边限制的流量和剩余的流量去较小值 
            if(!f) dis[v] = -1;//如果没有流量了,标记为-1,表示不能经过了 
            e[i].w -= f;//正边减流量 
            e[i ^ 1].w += f;//反边加流量 
            flow += f;//汇点流量加上获得的流量 
        }
    }
    return flow;
}

int dinic(){
    int maxflow = 0, flow = 0;
    while(bfs()){
        while(flow = dfs(s, INF)){
            maxflow += flow;
        }
    }
    return maxflow;
}

网络流-费用流

bool spfa(){
    bool flag = false;
    memset(dis, 0x3f, sizeof dis);
    memcpy(cur, head, sizeof head);
    deque<int> q;
    q.push_back(s);
    dis[s] = 0, vis[s] = true;
    while(!q.empty()){
        int u = q.front(); q.pop_front();
        vis[u] = false;
        for(int i = head[u]; i; i = e[i].nxt){
            int v = e[i].to;
            if(e[i].w && dis[v] > dis[u] + e[i].cost){
                dis[v] = dis[u] + e[i].cost;
                if(!vis[v]) {
                    vis[v] = true;
                    if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);
                    else q.push_back(v);
                }
                if(v == t) flag = true;
            }
        }
    }
    return flag;
}
 
int dfs(int u, int limit){
    if(u == t) return limit;//遇到汇点就返回 
    int flow = 0;
    vis[u] = true;
    for(int i = cur[u]; i && flow < limit; i = e[i].nxt){//指针:可以使cur[u]随i的变化而变化
        cur[u] = i; 
        int v = e[i].to;
        if(!vis[v] && e[i].w && dis[v] == dis[u] + e[i].cost){
            int f = dfs(v, min(e[i].w, limit - flow));
            if(!f) dis[v] = INF;
            res += f * e[i].cost;
            e[i].w -= f;
            e[i ^ 1].w += f;
            flow += f;
//            if(flow == limit) break;
        }
    }
    vis[u] = false;
    return flow;
}
 
int dinic(){
    int maxflow = 0, flow = 0;
    while(spfa()){
        while(flow = dfs(s, INF)){
            maxflow += flow;
        }
    }
    return maxflow;
}

DP 求树的直径

void dfs(int u, int fa) {
//    maxm[u] = minn[u] = 0;
    for(int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if(v == fa) continue;
        dfs(v, u);
        int t = maxm[v] + 1;
        if(t > maxm[u]) minn[u] = maxm[u], maxm[u] = t;
        else if(t > minn[u]) minn[u] = t;
    }
    ans = max(ans, maxm[u] + minn[u]);
}
posted @ 2021-05-21 21:50  Suzt_ilymtics  阅读(202)  评论(2编辑  收藏  举报