zoukankan      html  css  js  c++  java
  • 模板

    线段树 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 国际许可协议 进行许可。

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

  • 相关阅读:
    CF101B Buses
    CF1C Ancient Berland Circus
    学习笔记 莫比乌斯反演简单整理
    P3768 简单的数学题
    P2508 [HAOI2008]圆上的整点
    CF19E Fairy
    P1295 [TJOI2011]书架
    CF1148B Born This Way
    CF13E Holes
    CF1148C Crazy Diamond
  • 原文地址:https://www.cnblogs.com/Sam2007/p/14583646.html
Copyright © 2011-2022 走看看