模板

线段树 1

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
const LL N=1e5+2;
struct tree {
	LL l,r,sum,tag;
} tr[N<<2];
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sum(x) tr[x].sum
#define tag(x) tr[x].tag
LL a[N];
void build(LL x,LL l,LL r) {
	l(x)=l,r(x)=r;
	if(l==r) {
		sum(x)=a[l];
		return;
	}
	LL mid=(l+r)>>1;
	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
	sum(x)=sum(x<<1)+sum(x<<1|1);
}
inline void spread(int x) {
	if(tag(x)) {
		sum(x<<1)+=tag(x)*(r(x<<1)-l(x<<1)+1);
		sum(x<<1|1)+=tag(x)*(r(x<<1|1)-l(x<<1|1)+1);
		tag(x<<1)+=tag(x),tag(x<<1|1)+=tag(x),tag(x)=0;
	}
}
void add(LL x,LL l,LL r,LL del) {
	if(l<=l(x)&&r(x)<=r) {
		sum(x)+=del*(r(x)-l(x)+1);
		tag(x)+=del;
		return;
	}
	spread(x);
	LL mid=(l(x)+r(x))>>1;
	if(l<=mid) {
		add(x<<1,l,r,del);
	}
	if(mid<r) {
		add(x<<1|1,l,r,del);
	}
	sum(x)=sum(x<<1)+sum(x<<1|1);
}
LL query(LL x,LL l,LL r) {
	if(l<=l(x)&&r(x)<=r) {
		return sum(x);
	}
	spread(x);
	LL mid=(l(x)+r(x))>>1,sum=0;
	if(l<=mid) {
		sum=query(x<<1,l,r);
	}
	if(mid<r) {
		sum+=query(x<<1|1,l,r);
	}
	return sum;
}
int main() {
	LL n,m;
	scanf("%lld %lld",&n,&m);
	for(LL i=1; i<=n; i++) {
		scanf("%lld",a+i);
	}
	build(1,1,n);
	while(m--) {
		LL opt,x,y;
		scanf("%lld %lld %lld",&opt,&x,&y);
		if(opt^2) {
			LL k;
			scanf("%lld",&k);
			add(1,x,y,k);
		} else {
			printf("%lld
",query(1,x,y));
		}
	}
	return 0;
}

树状数组 1

#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x) {
	return x&(-x);
}
const int N=5e5+5;
int n,tr[N<<2];
inline void add(int x,int del) {
	while(x<=n) {
		tr[x]+=del,x+=lowbit(x);
	}
}
inline int query(int x) {
	int sum=0;
	while(x>0) {
		sum+=tr[x],x-=lowbit(x);
	}
	return sum;
}
int main() {
	int m;
	scanf("%d %d",&n,&m);
	for(int i=1,x; i<=n; i++) {
		scanf("%d",&x),add(i,x);
	}
	while(m--) {
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		if(x==1) {
			add(y,z);
		} else {
			printf("%d
",query(z)-query(y-1));
		}
	}
	return 0;
}

最小费用最大流

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
bool vis[N];
int n,m,s,t,x,y,z,f,dis[N],pre[N],last[N],flow[N],maxflow,mincost;
//dis最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量
struct Edge {
    int v,nxt,flow,dis;//flow流量 dis花费
} e[N];
int head[N],cnt;
queue<int> q;
void add_edge(int from,int v,int flow,int dis) {
    e[++cnt].nxt=head[from],e[cnt].v=v,e[cnt].flow=flow,e[cnt].dis=dis,head[from]=cnt;
}
bool spfa(int s,int t) {
    memset(dis,0x7f,sizeof(dis)),memset(flow,0x7f,sizeof(flow));
    memset(vis,0,sizeof(vis));
    q.push(s),vis[s]=1,dis[s]=0,pre[t]=-1;
    while(q.size()) {
        int now=q.front();
        q.pop(),vis[now]=0;
        for(int i=head[now]; i!=-1; i=e[i].nxt) {
            if(e[i].flow>0 && dis[e[i].v]>dis[now]+e[i].dis) {//正边
                dis[e[i].v]=dis[now]+e[i].dis,pre[e[i].v]=now;
				last[e[i].v]=i,flow[e[i].v]=min(flow[now],e[i].flow);
                if(!vis[e[i].v]) {
                    vis[e[i].v]=1,q.push(e[i].v);
                }
            }
        }
    }
    return pre[t]^-1;
}
int main() {
    memset(head,-1,sizeof(head)),cnt=-1;//初始化
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1; i<=m; i++) {
        scanf("%d%d%d%d",&x,&y,&z,&f);
        add_edge(x,y,z,f); add_edge(y,x,0,-f);
        //反边的流量为0,花费是相反数
    }
    while(spfa(s,t)) {
        int now=t;
        maxflow+=flow[t],mincost+=flow[t]*dis[t];
        while(now^s) {//从源点一直回溯到汇点
            e[last[now]].flow-=flow[t],e[last[now]^1].flow+=flow[t],now=pre[now];
        }
    }
    printf("%d %d",maxflow,mincost);
    return 0;
}

快速幂||取余运算

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
LL pow(LL x,LL y,LL p) {
	LL ans=1;
	while(y) {
		if(y&1) {
			ans=ans*x%p;
		}
		x=x*x%p,y>>=1;
	}
	return ans;
}
int main() {
	LL b,p,k;
	scanf("%lld %lld %lld",&b,&p,&k);
	printf("%lld^%lld mod %lld=%lld",b,p,k,pow(b,p,k)%k);
	return 0;
}

多项式乘法(FFT)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod=998244353,G=3,N=2200000;
LL n,m,iN,a[N],b[N],tr[N];
void inc(LL &a,LL b) {
	a+=b;
	if(a>=mod) {
		a-=mod;
	}
}
void dec(LL &a,LL b) {
	a-=b;
	if(a<0) {
		a+=mod;
	}
}
LL _inc(LL a,LL b) {
	a+=b;
	if(a>=mod) {
		a-=mod;
	}
	return a;
}
LL _dec(LL a,LL b) {
	a-=b;
	if(a<0) {
		a+=mod;
	}
	return a;
}
LL mi(LL a,LL k=mod-2) {
	LL sum=1;
	while(k) {
		if(k&1) {
			sum=sum*a%mod;
		}
		a=a*a%mod,k>>=1;
	}
	return sum;
}
const LL iG=mi(G);
void NTT(LL *f,bool flag) {
	for(LL i=0; i<n; i++) {if(i<tr[i]){swap(f[i],f[tr[i]]);
	}
	}
	for(LL p=2; p<=n; p<<=1) {
		LL angle=mi(flag?G:iG,(mod-1)/p);
		for(LL k=0; k<n; k+=p) {
			LL buf=1;
			for(LL i=k; i<k+p/2; i++) {
				LL tt=f[i+p/2]*buf%mod;
				f[i+p/2]=_dec(f[i],tt),inc(f[i],tt);
				buf=buf*angle%mod;
			}
		}
	}
}
int main() {
	scanf("%lld%lld",&n,&m);
	for(LL i=0; i<=n; i++) {
		scanf("%lld",a+i);
	}
	for(LL i=0; i<=m; i++) {
		scanf("%lld",b+i);
	}
	for(m+=n,n=1; n<=m; n<<=1);
	for(LL i=0; i<n; i++) {
		tr[i]=(tr[i>>1]>>1)|((i&1)?n>>1:0);
	}
	NTT(a,1),NTT(b,1);
	for(LL i=0; i<n; i++) {
		a[i]=a[i]*b[i]%mod;
	}
	NTT(a,0),iN=mi(n);
	for(LL i=0; i<=m; i++) {
		printf("%lld ",a[i]*iN%mod);
	}
}

KMP 字符串匹配

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+2;
int kmp[N]= {0};
char a[N],b[N];
int main() {
	scanf("%s%s",a+1,b+1);
	int la=strlen(a+1),lb=strlen(b+1),j=0;
	for(int i=2; i<=lb; i++) {
		while(j>0&&(b[i]^b[j+1])) {
			j=kmp[j];
		}
		if(b[i]==b[j+1]) {
			j++;
		}
		kmp[i]=j;
	}
	j=0;
	for(int i=1; i<=la; i++) {
		while(j>0&&(a[i]^b[j+1])) {
			j=kmp[j];
		}
		if(a[i]==b[j+1]) {
			j++;
		}
		if(j==lb) {
			printf("%d
",i-lb+1);
			j=kmp[j];
		}
	}
	for(int i=1; i<=lb; i++) {
		printf("%d ",kmp[i]);
	}
	return 0;
}

差分约束算法

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
struct edge {
	int v,w,nxt;
} e[N];
int n,m,head[N],cnt,dis[N],tot[N];
bitset<N> vis;
void add(int u,int v,int w) {
	e[++cnt].v=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;
}
bool spfa(int s) {
	queue<int> q;
	memset(dis,63,sizeof(dis));
	dis[s]=0,vis[s]=1;
	q.push(s);
	while(q.size()) {
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u]; i; i=e[i].nxt) {
			int v=e[i].v;
			if(dis[v]>dis[u]+e[i].w) {
				dis[v]=dis[u]+e[i].w;
				if(!vis[v]) {
					vis[v]=1,tot[v]++;
					if(tot[v]==n+1) {
						return 0;
					}
					q.push(v);
				}
			}
		}
	}
	return 1;
}
int main() {
	scanf("%d %d",&n,&m);
	for(int i=1; i<=n; i++) {
		add(0,i,0);
	}
	for(int i=1,v,u,w; i<=m; i++) {
		scanf("%d %d %d",&v,&u,&w),add(u,v,w);
	}
	if(!spfa(0)) {
		puts("NO");
		return 0;
	}
	for(int i=1; i<=n; i++) {
		printf("%d ",dis[i]);
	}
	return 0;
}

网络最大流

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
const LL N=1002,M=5002,inf=1e9;
struct edge {
	LL to,nxt,w;
} e[M<<1];
LL n,m,s,t,cnt=1,head[N],d[N];
void add(int u,int v,int w) {
	e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt,e[cnt].w=w;
}
bool bfs() {
	queue<LL> q;
	q.push(s);
	for(int i=1; i<=n; i++) {
		d[i]=inf;
	}
	d[s]=0;
	while(q.size()) {
		LL x=q.front();
		q.pop();
		for(LL i=head[x]; i; i=e[i].nxt) {
			LL v=e[i].to;
			if(e[i].w&&d[v]==inf) {
				q.push(v),d[v]=d[x]+1;
				if(v==t) {
					return 1;
				}
			}
		}
	}
	return 0;
}
LL dfs(LL x,LL sum) {
	if(x==t) {
		return sum;
	}
	LL res=0;
	for(int i=head[x]; i&&sum; i=e[i].nxt) {
		int v=e[i].to;
		if(e[i].w>0&&d[v]==d[x]+1) {
			int k=dfs(v,min(sum,e[i].w));
			if(!k) {
				d[v]=inf;
			}
			e[i].w-=k,e[i^1].w+=k,res+=k,sum-=k;
		}
	}
	return res;
}
int main() {
	scanf("%lld %lld %lld %lld",&n,&m,&s,&t);
	for(LL i=1,u,v,w; i<=m; i++) {
		scanf("%lld %lld %lld",&u,&v,&w),add(u,v,w),add(v,u,0);
	}
	LL ans=0;
	while(bfs()) {
		ans+=dfs(s,inf);
	}
	printf("%lld",ans);
	return 0;
}

卢卡斯定理

#include<bits/stdc++.h>
#define N 100010
using namespace std;
using LL=long long;
LL p,a[N];
LL pow(LL x,LL y) {
	x%=p;
	LL ans=1;
	while(y) {
		if(y&1) {
			ans=ans*x%p;
		}
		x=x*x%p,y>>=1;
	}
	return ans;
}
LL C(LL n,LL m) {
	if(m>n) {
		return 0;
	}
	return (a[n]*pow(a[m],p-2))%p*pow(a[n-m],p-2)%p;
}
LL Lucas(LL n,LL m) {
	if(!m) {
		return 1;
	}
	return C(n%p,m%p)*Lucas(n/p,m/p)%p;
}
int main() {
	LL T;
	scanf("%lld",&T);
	while(T--) {
		LL n,m;
		scanf("%lld %lld %lld",&n,&m,&p);
		a[0]=1;
		for(LL i=1; i<=p; i++) {
			a[i]=(a[i-1]*i)%p;
		}
		printf("%lld
",Lucas(n+m,n));
	}
}

树状数组 2

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+2;
int n,tr[N<<2];
inline int lowbit(int x) {
	return x&(-x);
}
void add(int p,int del) {
	while(p<=n) {
		tr[p]+=del;
		p+=lowbit(p);
	}
}
int query(int p) {
	int sum=0;
	while(p>0) {
		sum+=tr[p];
		p-=lowbit(p);
	}
	return sum;
}
int main() {
	int m;
	scanf("%d %d",&n,&m);
	int lst=0;
	for(int i=1,x; i<=n; i++) {
		scanf("%d",&x);
		add(i,x-lst);
		lst=x;
	}
	while(m--) {
		int op,x,y,k;
		scanf("%d %d",&op,&x);
		if(op^2) {
			scanf("%d %d",&y,&k);
			add(x,k),add(y+1,-k);
		} else {
			printf("%d
",query(x));
		}
	}
	return 0;
}

线性筛素数

#include<bits/stdc++.h>
using namespace std;
const int N=1e8+5;
int cnt,p[N];
bitset<N> is;
int main() {
	int n,q;
	scanf("%d %d",&n,&q);
	for(int i=2; i<=n; i++) {
		if(!is[i]) {
			p[++cnt]=i;
		}
		for(int j=1; j<=cnt; j++) {
			if(1LL*i*p[j]>=N) {
				break;
			}
			is[i*p[j]]=1;
			if(i*p[j]==0) {
				break;
			}
		}
	}
	while(q--) {
		int k;
		scanf("%d",&k),printf("%d
",p[k]);
	}
	return 0;
}

AC 自动机

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
int n;
int tr[N][26],tot,e[N],fail[N];
void insert(char *s) {
	int u=0;
	for(int i=1; s[i]; i++) {
		if(!tr[u][s[i]-'a']) {
			tr[u][s[i]-'a']=++tot;
		}
		u=tr[u][s[i]-'a'];
	}
	e[u]++;
}
void build() {
	queue<int> q;
	for(int i=0; i<26; i++) {
		if(tr[0][i]) {
			q.push(tr[0][i]);
		}
	}
	while(q.size()) {
		int u=q.front();
		q.pop();
		for(int i=0; i<26; i++) {
			if(tr[u][i]) {
				fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]);
			} else {
				tr[u][i]=tr[fail[u]][i];
			}
		}
	}
}
int query(char *s) {
	int u=0,res=0;
	for(int i=1; s[i]; i++) {
		u=tr[u][s[i]-'a'];
		for(int j=u; j&&e[j]^-1; j=fail[j]) {
			res+=e[j],e[j]=-1;
		}
	}
	return res;
}
char s[N];
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
		scanf("%s",s+1),insert(s);
	}
	build(),scanf("%s",s+1),printf("%d",query(s));
	return 0;
}

二分图最大匹配

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,e,ans,match[N];
bool a[N][N],vis[N];
bool dfs(int x) {
	for(int i=1; i<=m; i++) {
		if(!vis[i]&&a[x][i]) {
			vis[i]=1;
			if(!match[i]||dfs(match[i])) {
				match[i]=x;
				return 1;
			}
		}
	}
	return 0;
}
int main() {
	scanf("%d %d %d",&n,&m,&e);
	for(int i=1,u,v; i<=e; i++) {
		scanf("%d %d",&u,&v),a[u][v]=1;
	}
	for (int i=1; i<=n; i++){
        ans+=dfs(i);
        memset(vis,0,sizeof(vis));
    }
    printf("%d",ans);
	return 0;
}

可持久化线段树 1

#include<bits/stdc++.h>
using namespace std;
struct abc {
	int l,r,val;
} tree[1000001<<5];
int top,a[1000005],root[1000005];
int New(int node) {
	tree[++top]=tree[node];
	return top;
}
int build(int node,int begin,int end) {
    node=++top;
    if(begin==end) {
        tree[node].val=a[begin];
        return top;
    }
    int mid=(begin+end)>>1;
    tree[node].l=build(tree[node].l,begin,mid);
    tree[node].r=build(tree[node].r,mid+1,end);
    return node;
}
int update(int node,int begin,int end,int x,int val) {
    node=New(node);
    if(begin==end) {
        tree[node].val=val;
    } else {
        int mid=(begin+end)>>1;
        if(x<=mid) {
            tree[node].l=update(tree[node].l,begin,mid,x,val);
        } else {
            tree[node].r=update(tree[node].r,mid+1,end,x,val);
        }
    }
    return node;
}
int query(int node,int begin,int end,int x) {
    if(begin==end) {
        return tree[node].val;
    } else {
        int mid=(begin+end)>>1;
        if(x<=mid) {
            return query(tree[node].l,begin,mid,x);
        } else {
            return query(tree[node].r,mid+1,end,x);
        }
    }
}
int main(){
	int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1; i<=n; i++) {
    	scanf("%d",a+i);
    }
    root[0]=build(0,1,n);
    for(int i=1,rt,mode,x; i<=m; i++){
        scanf("%d %d %d",&rt,&mode,&x);
        if(mode==1) {
        	int y;
            scanf("%d",&y);
            root[i]=update(root[rt],1,n,x,y);
        } else {
            printf("%d
",query(root[rt],1,n,x));
            root[i]=root[rt];
        }
    }
}

ST表

#include<bits/stdc++.h>
using namespace std;
int f[100005][40];
inline int ask(int l,int r) {
	int k=(int)(log(r-l+1)/log(2));
	return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main() {
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1; i<=n; i++) {
		scanf("%d",f[i]);
	}
	int t=log2(n);
	for(int j=1; j<=t; j++) {
		for (int i=1; i<=n-(1<<j)+1; i++) {
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1,l,r; i<=m; i++) {
		scanf("%d %d",&l,&r);
		printf("%d
",ask(l,r));
	}
	return 0;
}

nim 游戏

#include<bits/stdc++.h>
using namespace std;
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		int n;
		scanf("%d",&n);
		int tmp;
		scanf("%d",&tmp);
		for(int i=1; i<n; i++) {
			int x;
			scanf("%d",&x),tmp^=x;
		}
		if(tmp) {
			puts("Yes");
		} else {
			puts("No");
		}
	}
	return 0;
}

乘法逆元

#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int ans=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') {
			f=-1;
		}
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		ans=(ans<<3)+(ans<<1)+(c-'0');
		c=getchar();
	}
	return ans*f;
}
inline void print(int x) {
	if(x<0) {
		x*=-1,putchar('-');
	}
	if(x>9) {
		print(x/10);
	}
	putchar(x%10+'0');
}
int ans[3000005]= {0,1};
int main() {
	int n=read(),p=read();
	putchar('1'),putchar('
');
	for(int i=2; i<=n; i++) {
		ans[i]=1LL*(p-p/i)*ans[p%i]%p;
		print(ans[i]),putchar('
');
	}
}

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

限于本人水平,如果文章有表述不当之处,还请不吝赐教。

原文地址:https://www.cnblogs.com/Sam2007/p/14583646.html