🖕谢谢光临�|

Wubaozi123awa

园龄:6个月粉丝:0关注:0

CSP-S可能出现的模板(非原创,各个地方整理得)

CSP-S rp+++++++++++

数学

快速幂

int pw(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=(res*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return res;
}

Lucas(附赠线性求逆元)

int ny[N],jc[N],jcny[N];
void init(){
    ny[1]=1;
    for(int i=2;i<N;i++) ny[i]=(mod-mod/i)*ny[mod%i]%mod;
    jcny[0]=jcny[1]=1;
    for(int i=2;i<N;i++) jcny[i]=jcny[i-1]*ny[i]%mod;
    jc[0]=jc[1]=1;
    for(int i=2;i<N;i++) jc[i]=jc[i-1]*i%mod;
}
int c(int a,int b){
	if(b>a) return 0;
	return jc[a]*jcny[a-b]%mod*jcny[b]%mod;
}
int lucas(int a,int b){
    if(!b) return 1;
    return c(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}

exgcd

int exgcd(int a,int b,int &x,int &y){
	if(!b){
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return d;
}

exgcd求逆元

ll inv(ll a, ll m){
    ll x, y;
    ll d = exgcd(a, m, x, y);
    return d == 1 ? (x + m) % m : -1;
}

费马小定理求逆元

ll inv(ll a, ll p) { return Pow(a, p - 2, p); }

线性求逆元

for (int i = 2; i < n; i++) inv[i] = inv[p % i] * (p - p / i) % p;

线性同余方程(删除原因:没有仔细阅读 这是拓展大步小步)

ll exbsgs(ll a, ll b, ll p){
    if (b == 1LL) return 0;
    ll t, d = 1, k = 0;
    while ((t = gcd(a, p)) != 1){
        if (b % t) return -1;
        ++k, b /= t, p /= t, d = d * (a / t) % p;
        if (b == d) return k;
    }
    map<ll, ll> dic;
    ll m = ceil(sqrt(p));
    ll a_m = Pow(a, m, p), mul = b;
    for (ll j = 1; j <= m; ++j) mul = mul * a % p, dic[mul] = j;
    for (ll i = 1; i <= m; ++i){
        d = d * a_m % p;
        if (dic[d]) return i * m - dic[d] + k;
    }
    return -1;
}

CRT

LL CRT(int k, LL* a, LL* r) {
  LL n = 1, ans = 0;
  for (int i = 1; i <= k; i++) n = n * r[i];
  for (int i = 1; i <= k; i++) {
    LL m = n / r[i], b, y;
    exgcd(m, r[i], b, y);  // b * m mod r[i] = 1
    ans = (ans + a[i] * m * b % n) % n;
  }
  return (ans % n + n) % n;
}

exCRT

ll excrt(){
    M=b[1];
    ans=a[1];
    for(ll i=2;i<=n;++i){
        ll c=((a[i]-ans)%b[i]+b[i])%b[i];
        ll g=exgcd(M,b[i],x,y);
        ll p=b[i]/g;
        x=mul(x,c/g,p);
        ans+=x*M;
        M*=p;
        ans=(ans%M+M)%M;
    }
    return ans;
}

欧拉筛

bool vis[N];
int p[N],phi[N],cnt=1;
void initphi(){
	phi[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i]){
			p[cnt++]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<cnt&&i*p[j]<N;j++){
			vis[i*p[j]]=1;
			if(i%p[j]==0){
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			else phi[i*p[j]]=phi[i]*phi[p[j]];
		}
	}
}

Miller Rabin

bool Miller_Rabin(ll n, int s){
    if (n == 2) return 1;
    if (n < 2 || !(n & 1)) return 0;
    int t = 0;
    ll x, y, u = n - 1;
    while ((u & 1) == 0) t++, u >>= 1;
    for (int i = 0; i < s; i++){
        ll a = rand() % (n - 1) + 1;
        ll x = Pow(a, u, n);
            for (int j = 0; j < t; j++){
                ll y = Mul(x, x, n);
                if (y == 1 && x != 1 && x != n - 1) return 0;
                x = y;
            }
        if(x != 1) return 0;
    }
    return 1;
}

欧拉函数(单个)

ll euler(ll n){
    ll rt = n;
    for (int i = 2; i * i <= n; i++){
        if (n % i == 0){
            rt -= rt / i;
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) rt -= rt / n;
    return rt;
}

除法分块

for(int l=1,r;l<=n;l=r+1){
	r=(n/(n/l));
	cout<<(n/l)<<' '<<(r-l+1)<<endl;
}

扫描线

#include <stdio.h>
#include <iostream>
#include <algorithm>
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
const int MAXN = 1e6 + 10;
typedef long long ll;

int n, cnt = 0;
ll x1, y1, x2, y2, X[MAXN << 1];

struct ScanLine {
	ll l, r, h;
	int mark;
//  mark用于保存权值 (1 / -1)
	bool operator < (const ScanLine &rhs) const {
		return h < rhs.h;
	}
} line[MAXN << 1];

struct SegTree {
	int l, r, sum;
	ll len;
//  sum: 被完全覆盖的次数;
//  len: 区间内被截的长度。
} tree[MAXN << 2];

void build_tree(int x, int l, int r) {
//  我觉得最不容易写错的一种建树方法
	tree[x].l = l, tree[x].r = r;
	tree[x].len = 0;
	tree[x].sum = 0;
	if(l == r)
		return;
	int mid = (l + r) >> 1;
	build_tree(lson, l, mid);
	build_tree(rson, mid + 1, r);
	return;
}

void pushup(int x) {
	int l = tree[x].l, r = tree[x].r;
	if(tree[x].sum /* 也就是说被覆盖过 */ )
		tree[x].len = X[r + 1] - X[l];
//      更新长度        
	else
		tree[x].len = tree[lson].len + tree[rson].len;
//      合并儿子信息
}

void edit_tree(int x, ll L, ll R, int c) {
	int l = tree[x].l, r = tree[x].r;
//  注意,l、r和L、R的意义完全不同
//  l、r表示这个节点管辖的下标范围
//  而L、R则表示需要修改的真实区间
	if(X[r + 1] <= L || R <= X[l])
		return;
//  这里加等号的原因:
//  假设现在考虑 [2,5], [5,8] 两条线段,要修改 [1,5] 区间的sum
//  很明显,虽然5在这个区间内,[5,8] 却并不是我们希望修改的线段
//  所以总结一下,就加上了等号
	if(L <= X[l] && X[r + 1] <= R) {
		tree[x].sum += c;
		pushup(x);
		return;
	}
	edit_tree(lson, L, R, c);
	edit_tree(rson, L, R, c);
	pushup(x);
}

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		scanf("%lli %lli %lli %lli", &x1, &y1, &x2, &y2);
		X[2 * i - 1] = x1, X[2 * i] = x2;
		line[2 * i - 1] = (ScanLine) {x1, x2, y1, 1};
		line[2 * i] = (ScanLine) {x1, x2, y2, -1};
//      一条线段含两个端点,一个矩形的上下边都需要扫描线扫过
	}
	n <<= 1;
//  直接把 n <<= 1 方便操作
	sort(line + 1, line + n + 1);
	sort(X + 1, X + n + 1);
	int tot = unique(X + 1, X + n + 1) - X - 1;
//  去重最简单的方法:使用unique!(在<algorithm>库中)
	build_tree(1, 1, tot - 1);
//  为什么是 tot - 1 :
//  因为右端点的对应关系已经被篡改了嘛…
//  [1, tot - 1]描述的就是[X[1], X[tot]]
	ll ans = 0;
	for(int i = 1; i < n /* 最后一条边是不用管的 */ ; i++) {
		edit_tree(1, line[i].l, line[i].r, line[i].mark);
//      先把扫描线信息导入线段树
		ans += tree[1].len * (line[i + 1].h - line[i].h);
//      然后统计面积
	}
	printf("%lli", ans);
	return 0;
}

高斯消元

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+5;
int n;
double a[N][N],eps=1e-6;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n+1;j++){
			cin>>a[i][j];
		}
	}
	int now=1;
	for(int i=1;i<=n;i++){
		int pos=now;
		for(int j=now;j<=n;j++){
			if(abs(a[j][i])>abs(a[pos][i])){
				pos=j;
			}
		}
		if(abs(a[pos][i])<eps){
			continue;
		}
		swap(a[now],a[pos]);
		for(int j=n+1;j>=i;j--){
			a[now][j]/=a[now][i];
		}
		for(int j=now+1;j<=n;j++){
			for(int k=n+1;k>=i;k--){
				a[j][k]-=a[now][k]*a[j][i];
			}
		}
		now++;
	}
	if(now<=n){
		for(int i=now;i<=n;i++){
			if(abs(a[i][n+1])>eps){
				cout<<-1;
				return 0;
			}
		}
		cout<<0;
		return 0;
	}
	for(int i=n;i>=1;i--){
		for(int j=i+1;j<=n;j++){
			a[i][n+1]-=a[i][j]*a[j][n+1];
		}
	}
	for(int i=1;i<=n;i++){
		cout<<"x"<<i<<"="<<a[i][n+1]<<'\n';
	}
}

数据结构~

单调栈

void insert(int x){
    while(!sta.empty()&&sta.top()<x)sta.pop();
    sta.push(x);
}

单调队列

deque<int>d;
for(int i=1;i<=n;i++){
    cin>>a;
    while(!d.empty()&&d.end()>a)d.pop_back();
    d.push_back(a);
}

01trie~

int t[N*31][2],nv=1;
void build(int p,int d,int v){
	bool flag=(v&(1<<d));
	if(!t[p][flag]) t[p][flag]=++nv;
	if(d) build(t[p][flag],d-1,v);
}
int query(int p,int d,int v){
	if(d<0) return 0;
	bool flag=(v&(1<<d));
	if(t[p][!flag]) return (1<<d)+query(t[p][!flag],d-1,v);
	if(t[p][flag]) return query(t[p][flag],d-1,v);
}

ST表

#include <bits/stdc++.h>
using namespace std;
const int logn = 21;
const int maxn = 2000001;
int f[maxn][logn + 1], Logn[maxn + 1];

int read() {  // 快读
  char c = getchar();
  int x = 0, f = 1;
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * f;
}

void pre() {  // 准备工作,初始化
  Logn[1] = 0;
  Logn[2] = 1;
  for (int i = 3; i < maxn; i++) {
    Logn[i] = Logn[i / 2] + 1;
  }
}

int main() {
  int n = read(), m = read();
  for (int i = 1; i <= n; i++) f[i][0] = read();
  pre();
  for (int j = 1; j <= logn; j++)
    for (int i = 1; i + (1 << j) - 1 <= n; i++)
      f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);  // ST表具体实现
  for (int i = 1; i <= m; i++) {
    int x = read(), y = read();
    int s = Logn[y - x + 1];
    printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s]));
  }
  return 0;
}

树状数组

#define lower_bit(x) (x)&-(x)
using namespace std;
int n,m,tree[200000+10];
void add(int a,int c){
    for(int i=a;i<=n;i+=lower_bit(i))tree[i]+=c;
}
int find(int r){
    int ret=0;
    for(int i=r;i>=1;i-=lower_bit(i))ret+=tree[i];
    return ret;
}

线段树~

void addtag(int iSeg,int val){
	tr[iSeg].tag+=val;
	tr[iSeg].sum+=(tr[iSeg].r-tr[iSeg].l+1)*val;
}
void pushup(int iSeg){
	tr[iSeg].sum=tr[lsp].sum+tr[rsp].sum;
}
void pushdown(int iSeg){
	addtag(lsp,tr[iSeg].tag);
	addtag(rsp,tr[iSeg].tag);
	tr[iSeg].tag=0;
}
void build(int iSeg,int l,int r){
	tr[iSeg].l=l; tr[iSeg].r=r;
	if(l==r){
		tr[iSeg].sum=x[l];
		tr[iSeg].tag=0;
		return;
	}
	int mid=l+(r-l)/2;
	build(lsp,l,mid); build(rsp,mid+1,r);
	pushup(iSeg);
}
void modify(int iSeg,int l,int r,int val){
	if(l<=tr[iSeg].l&&tr[iSeg].r<=r){
		addtag(iSeg,val);
		return;
	}
	pushdown(iSeg);
	if(l<=tr[lsp].r)modify(lsp,l,r,val);
	if(tr[rsp].l<=r)modify(rsp,l,r,val);
	pushup(iSeg);
}
int query(int iSeg,int l,int r){
//	cout<<iSeg<<" "<<l<<" "<<r<<" "<<tr[iSeg].l<<" "<<tr[iSeg].r<<endl;
	if(l<=tr[iSeg].l&&tr[iSeg].r<=r) return tr[iSeg].sum;
	pushdown(iSeg);
	int sum=0;
	if(l<=tr[lsp].r)sum+=query(lsp,l,r);
	if(tr[rsp].l<=r)sum+=query(rsp,l,r);
	return sum;
}

fhq treap~

mt19937 rnd(time(0));
const int Max_n=1e6+10;
class Node{
    public:
    int l_son=0,r_son=0;
    int val,ind,size=0;
    Node(){
        l_son=r_son=size=0;
    }
};
class treap{
    public:
    int size,root;
    Node fhq[Max_n];
    int new_node(int x){
        fhq[++size].val=x;
        fhq[size].ind=rnd();
        fhq[size].l_son=fhq[size].r_son=0;
        fhq[size].size=1;
        return size;
    }
    treap(){
        size=0,root=0;
    }
    void push_up(int x){
        fhq[x].size=fhq[fhq[x].l_son].size+fhq[fhq[x].r_son].size+1;
    }
    void split(int x,int k,int &l,int &r){
        if(!x){
            l=r=0;
            return;
        }else if(fhq[x].val<=k){l=x;split(fhq[x].r_son,k,fhq[x].r_son,r);}
        else{r=x;split(fhq[x].l_son,k,l,fhq[x].l_son);}
        push_up(x);
    }
    int merge(int x,int y){
        if(!x||!y)return x+y;
        if(fhq[x].ind>fhq[y].ind){
            fhq[x].r_son=merge(fhq[x].r_son,y);
            push_up(x);
            return x;
        }else{
            fhq[y].l_son=merge(x,fhq[y].l_son);
            push_up(y);
            return y;
        }
    }
    void insert(int val){
        int a,b=0;
        split(root,val,a,b);
        root=merge(merge(a,new_node(val)),b);
    }
    void del(int val){
        int a,b,c=0;
        split(root,val,a,b);
        split(a,val-1,a,c);
        c=merge(fhq[c].l_son,fhq[c].r_son);
        root=merge(merge(a,c),b);
    }
    int get_rnk(int val){
        int a,b;
        split(root,val-1,a,b);
        int ret=fhq[a].size;
        root=merge(a,b);
        return ret+1;
    }
    int get_num(int rnk){
        int now=root;
        while(now){
            if(fhq[fhq[now].l_son].size+1==rnk)break;
        else if(fhq[fhq[now].l_son].size+1>rnk)now=fhq[now].l_son;
            else{
                rnk-=fhq[fhq[now].l_son].size+1;
                now=fhq[now].r_son;
            }
        }
        return fhq[now].val;
    }
    int pre(int val){
        int a,b=0;
        split(root,val-1,a,b);
        int now=a;
        while(fhq[now].r_son)now=fhq[now].r_son;
        int pr=fhq[now].val;
        root=merge(a,b);
        return pr;
    }
    int sub(int val){
        int a,b=0;
        split(root,val,a,b);
        int now=b;
        while(fhq[now].l_son)now=fhq[now].l_son;
        int su=fhq[now].val;
        root=merge(a,b);
        return su;
    }
};

除法分块

for(int l=1,r;l<=n;l=r+1){
	r=(n/(n/l));
	cout<<(n/l)<<' '<<(r-l+1)<<endl;
}

字符串

AC自动机(/KMP)

struct kkk{
    int son[26],fail,flag,ans;
    void clear(){memset(son,0,sizeof(son)),fail=flag=ans=0;}
}trie[maxn];
queue<int>q;
void insert(char* s,int num){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++){
        int v=s[i]-'a';
        if(!trie[u].son[v])trie[u].son[v]=++cnt;
        u=trie[u].son[v];
    }
    if(!trie[u].flag)trie[u].flag=num;
    Map[num]=trie[u].flag;
}
void getFail(){
    for(int i=0;i<26;i++)trie[0].son[i]=1;
    q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        int Fail=trie[u].fail;
        for(int i=0;i<26;i++){
            int v=trie[u].son[i];
            if(!v){trie[u].son[i]=trie[Fail].son[i];continue;}
            trie[v].fail=trie[Fail].son[i]; in[trie[v].fail]++;
            q.push(v);
        }
    }
}
void topu(){
    for(int i=1;i<=cnt;i++)
    if(in[i]==0)q.push(i);
    while(!q.empty()){
        int u=q.front();q.pop();vis[trie[u].flag]=trie[u].ans;
        int v=trie[u].fail;in[v]--;
        trie[v].ans+=trie[u].ans;
        if(in[v]==0)q.push(v);
    }
}
void query(char* s){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++)
    u=trie[u].son[s[i]-'a'],trie[u].ans++;
}

字符串哈希

typedef unsigned long long ull;
const ull Seed_Pool[] = {146527, 19260817};
const ull Mod_Pool[] = {1000000009, 998244353};
struct Hash{
    ull SEED, MOD;
    vector<ull> p, h;
    Hash() {}
    Hash(const string& s, const int& seed_index, const int& mod_index){
        SEED = Seed_Pool[seed_index];
        MOD = Mod_Pool[mod_index];
        int n = s.length();
        p.resize(n + 1), h.resize(n + 1);
        p[0] = 1;
        for (int i = 1; i <= n; i++) p[i] = p[i - 1] * SEED % MOD;
        for (int i = 1; i <= n; i++) h[i] = (h[i - 1] * SEED % MOD + s[i - 1]) % MOD;
    }
    ull get(int l, int r) { return (h[r] - h[l] * p[r - l] % MOD + MOD) % MOD; }
    ull substr(int l, int m) { return get(l, l + m); }
};

图论

链式前向星

struct edge{int to,w,nxt;}e[M*2];
int hed[N],ecnt;
void add(int l,int r,int c){
	e[++ecnt]=(edge){r,c,hed[l]};
	hed[l]=ecnt;
}

dijkstra

struct edge{int to,w;};
vector<edge> e[N];
struct node{
	int u,d;
	bool operator<(const node&tmp)const{return d>tmp.d;}
};
priority_queue<node> q;
int dis[N];
bool vis[N];
void dijkstra(){
	memset(dis,0x3f,sizeof dis);
	q.push((node){s,0});
	dis[s]=0;
	while(!q.empty()){
		int u=q.top().u;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=0;i<e[u].size();i++){
			int v=e[u][i].to,cost=dis[u]+e[u][i].w;
			if(dis[v]>cost){
				dis[v]=cost;
				q.push((node){v,cost});
			}
		}
	}
}

熟练剖粪树链剖分+树链剖分LCA

void dfs(int u,int f){
    size[u]=1;
    for(int &v:V[u]){
        if(v!=f){
            fa[v]=u,deep[v]=deep[u]+1;dfs(v,u);size[u]+=size[v];
            if(size[v]>=size[hson[u]])hson[u]=v,swap(v,V[u][0]);
        } 
    }
}
void dfs2(int u,int f,int tp){
    dfn[u]=cnt++,rnk[dfn[u]]=u,top[u]=tp;
    for(int &v:V[u]){
        if(v!=f){if(hson[u]==v)dfs2(v,u,tp);else dfs2(v,u,v);}
    }
}
int LCA(int a,int b){
    while(top[a]!=top[b]){
        if(deep[top[b]]>deep[top[a]])swap(a,b);
        a=fa[top[a]];
    }
    return deep[a]>deep[b]?b:a;
}

倍增LCA

void dfs(int root, int fno) {
  fa[root][0] = fno;
  dep[root] = dep[fa[root][0]] + 1;
  for (int i = 1; i < 31; ++i) {
    fa[root][i] = fa[fa[root][i - 1]][i - 1];
    cost[root][i] = cost[fa[root][i - 1]][i - 1] + cost[root][i - 1];
  }
  int sz = v[root].size();
  for (int i = 0; i < sz; ++i) {
    if (v[root][i] == fno) continue;
    cost[v[root][i]][0] = w[root][i];
    dfs(v[root][i], root);
  }
}
int lca(int x, int y) {
  if (dep[x] > dep[y]) swap(x, y);
  int tmp = dep[y] - dep[x], ans = 0;
  for (int j = 0; tmp; ++j, tmp >>= 1)
    if (tmp & 1) ans += cost[y][j], y = fa[y][j];
  if (y == x) return ans;
  for (int j = 30; j >= 0 && y != x; --j) {
    if (fa[x][j] != fa[y][j]) {
      ans += cost[x][j] + cost[y][j];
      x = fa[x][j];
      y = fa[y][j];
    }
  }
  ans += cost[x][0] + cost[y][0];
  return ans;
}

缩点tarjan

	dfn[u]=low[u]=++cnt;vis[u]=1;
	st.push(u);
	for(auto v:V[u]){
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		int p=0;scnt++; 
		do{
			p=st.top(),vis[p]=0,scc[p]=scnt;
			sc[scnt].push_back(p);
			st.pop();
		}while(p!=u);
	}
}

拓扑排序

bool toposort() {
  vector<int> L;
  queue<int> S;
  for (int i = 1; i <= n; i++)
    if (in[i] == 0) S.push(i);
  while (!S.empty()) {
    int u = S.front();
    S.pop();
    L.push_back(u);
    for (auto v : G[u]) {
      if (--in[v] == 0) {
        S.push(v);
      }
    }
  }
  if (L.size() == n) {
    for (auto i : L) cout << i << ' ';
    return true;
  } else {
    return false;
  }
}

MST

for(int i=1;i<=n;i++)fa[i]=i;
while(!Q1.empty()){
    auto [c,u,v]=Q1.top();Q1.pop();
    if(find(u)==find(v))continue;
    if(!(n--)||!(k--))break;
	add(u,v);
	ans=max(ans,c);
}

dinic

int n,m,s,t,u,v,dis[N],hed[N],rad[N];
struct edge{int to,w,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w){
    e[++ecnt]=(edge){v,w,hed[u]};
    hed[u]=ecnt;
}
void link(int u,int v,int w){
	add(u,v,w);
	add(v,u,0);
}
bool bfs(){
	queue<int> q;
	for(int i=s;i<=t;i++) dis[i]=-1;
	dis[s]=0;
	q.push(s);
	while(!q.empty()){
		int cur=q.front();
		rad[cur]=hed[cur];
		q.pop();
		for(int i=hed[cur];i;i=e[i].nxt){
			if(dis[e[i].to]==-1&&e[i].w){
				dis[e[i].to]=dis[cur]+1;  
				q.push(e[i].to);
			}
		}
	}
	return dis[t]!=-1;
}
int dfs(int x,int flow){
	if(x==t) return flow;
	int cnt=0;
	for(int i=rad[x];i&&flow;i=e[i].nxt){ 
		rad[x]=i;
		if(dis[e[i].to]==dis[x]+1&&e[i].w){
			int ret=dfs(e[i].to,min(flow,e[i].w)); 
			if(ret>0){
				e[i].w-=ret; 
				e[i^1].w+=ret;
				cnt+=ret;
				flow-=ret;
			}
		}
	}
	return cnt; 
}

MCMF

int n,m,s,t,dis[N],hed[N],rad[N],ans1,ans2;
bool vis[N];
struct edge{int to,w,c,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w,int c){
    e[++ecnt]=(edge){v,w,c,hed[u]};
    hed[u]=ecnt;
}
void link(int u,int v,int w,int c){
	add(u,v,w,c);
	add(v,u,0,-c);
}
#define TO e[i].to
#define COST dis[x]+e[i].c
bool spfa(){
	for(int i=s;i<=t;i++) dis[i]=1e9;
	for(int i=s;i<=t;i++) vis[i]=0;
	queue<int> q;
	q.push(s);
	vis[s]=1,dis[s]=0;
	while(!q.empty()){
		int x=q.front();
		rad[x]=hed[x];
		q.pop();
		vis[x]=0;
		for(int i=hed[x];i;i=e[i].nxt)if(dis[TO]>COST&&e[i].w){
			dis[TO]=COST;
			if(!vis[TO]){
				q.push(TO);
				vis[TO]=1;
			}
		}
	}
	return dis[t]!=1e9;
}
int dfs(int x,int flow){
	if(x==t) return flow;
	vis[x]=1;
	int cnt=0;
	for(int i=rad[x];i&&flow;i=e[i].nxt){ 
		rad[x]=i;
		if(!vis[TO]&&dis[TO]==COST&&e[i].w){
			int ret=dfs(TO,min(flow,e[i].w));
			e[i].w-=ret; 
			e[i^1].w+=ret;
			cnt+=ret;
			flow-=ret;
			ans2+=ret*e[i].c;
		}
	}
	vis[x]=0;
	return cnt; 
}

其他

矩阵快速幂

typedef vector<ll> vec;
typedef vector<vec> mat;
mat mul(mat& A, mat& B){
    mat C(A.size(), vec(B[0].size()));
    for (int i = 0; i < A.size(); i++)
    for (int k = 0; k < B.size(); k++)
    if (A[i][k]) // 对稀疏矩阵的优化
    for (int j = 0; j < B[0].size(); j++)
    C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
    return C;
}
mat Pow(mat A, ll n){
    mat B(A.size(), vec(A.size()));
    for (int i = 0; i < A.size(); i++) B[i][i] = 1;
    for (; n; n >>= 1, A = mul(A, A))
    if (n & 1) B = mul(B, A);
    return B;
}

本文作者:baoziawa

本文链接:https://www.cnblogs.com/baoziawa/p/18503304

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Wubaozi123awa  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起