• NOIP前的模板


    1.筛(phi)

    (logn)求少数(phi)

    inline int phi(R int x){
    	R int res=x,tmp=x;
    	for(R int i=2;i*i<=x;i++){
    		if(tmp%i==0)res=res*(i-1)/i;
    		while(tmp%i==0)tmp/=i;
    	}
    	if(tmp>1)res=res*(tmp-1)/tmp;
    	return res;
    }
    

    线性求(phi)

    inline void getphi(R int n){
    	vis[1]=0;
    	for(R int i=2;i<=n;i++){
    		if(!vis[i]){
    			prime[++tot]=i;
    			phi[i]=i-1;
    		}
    		for(R int j=1;j<=tot&&i*prime[j]<=n;j++){
    			vis[prime[j]*i]=1;
    			if(i%prime[j]==0){
    				phi[prime[j]*i]=phi[i]*prime[j];break;
    			}
    			else phi[prime[j]*i]=phi[i]*(priem[j]-1);
    		}
    	}
    }
    

    线性筛约数个数和约数和

    //num[i] 表示i的最小质因子出现次数
    inline void get_d(){
    	d[1]=1;num[1]=1;
    	for(R int i=2;i<=n;i++){
    		if(!vis[i]){
    			prime[++tot]=i;
    			d[i]=2;num[i]=1;
    		}
    		for(R int j=1;j<=tot&&i*prime[j]<=n;j++){
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0){
    				num[i*prime[j]]=num[i]+1;
    				d[i*prime[j]]=d[i]/num[i*prime[j]]*(num[i*prime[j]]+1);
    				break;
    			}
    			d[prime[j]*i]=d[i]*(1+1);
    			num[prime[j]*i]=1;
    		}
    	}
    	
    }
    //sp[i] 表示i的(1+p[1]+p[1]^1+...+p[1]^a[1])
    inline void get_sd(){
    	sd[1]=1;sp[1]=1;
    	for(R int i=2;i<=n;i++){
    		if(!vis[i]){
    			prime[++tot]=i;
    			sd[i]=i+1;
    			sp[i]=i+1;
    		}
    		for(R int j=1;j<=tot&&prime[j]*i<=n;j++){
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0){
    				sp[i*prime[j]]=sp[i]*prime[j]+1;
    				sd[i*prime[j]]=sd[i]/sp[i]*sp[i*prime[j]];
    				break;
    			}
    			sd[i*prime[j]]=sd[i]*sd[prime[j]];
    			sp[i*prime[j]]=prime[j]+1;
    		}
    	}
    }
    

    2.ST表

    inline void pre(){
    	mn[0]=-1;
    	for(R int i=1;i<=n;i++){
    		mn[i]=((i&(i-1))==0)? mn[i-1]+1:mn[i-1];
    		stmax[i][0]=a[i];
    	}
    	for(R int j=1;j<=mn[n];j++)
    		for(R int i=1;i+(1<<j)-1<=n;i++)
    			stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
    } 
    inline int getmax(R int l,R int r){
    	R int k=mn[r-l+1];
    	return max(stmax[l][k],stmax[r-(1<<k)+1][k]);
    }
    int main(){
    	read(n);read(m);
    	for(R int i=1;i<=n;i++)read(a[i]);
    	pre();
    	for(R int i=1;i<=m;i++){
    		read(l);read(r);
    		printf("%d
    ",getmax(l,r));
    	}
        return 0;
    }
    

    3.高斯消元

    read(n);
    for(R int i=1;i<=n;i++)
        for(R int j=1;j<=n+1;j++)
            scanf("%lf",&mp[i][j]);
    for(R int i=1;i<=n;i++){
        R int mx=i;
        for(R int j=i+1;j<=n;j++)
            if(fabss(mp[mx][i])<fabss(mp[j][i]))mx=i;
        if(mx!=i)swap(mp[mx],mp[i]);
        if(fabss(mp[i][i])>eps){
            R double div=mp[i][i];
            for(R int j=i;j<=n+1;j++)
                mp[i][j]/=div;
            for(R int j=1;j<=n;j++){
                if(i==j)continue;
                div=mp[j][i];
                for(R int k=i;k<=n+1;k++)
                    mp[j][k]-=div*mp[i][k];
            }
        }
    }
    for(R int i=1;i<=n;i++){
        R int cnt=1;
        while(fabss(mp[i][cnt])<eps&&cnt<=n+1)cnt++;
        if(cnt==n+1)pd_nojie=1;
        if(cnt>n+1)pd_wuqiong=1;
    }
    if(pd_nojie||pd_wuqiong){
        printf("No Solution
    ");
        return 0;
    }
    ans[n]=mp[n][n+1];
    for(R int i=n-1;i>=1;i--){
        ans[i]=mp[i][n+1];
        for(R int j=i+1;j<=n;j++)
            ans[i]-=mp[i][j]*ans[j];
    }
    for(R int i=1;i<=n;i++)
        printf("%.2lf
    ",ans[i]);
    

    4.悬线法

    for(R int i=1;i<=n;i++){
        for(R int j=1;j<=m;j++){
            read(mp[i][j]);
            up[i][j]=1;
            l[i][j]=r[i][j]=j;
        }
    }
    for(R int i=1;i<=n;i++)
        for(R int j=2;j<=m;j++)
            if(mp[i][j]!=mp[i][j-1])
                l[i][j]=l[i][j-1];
    for(R int i=1;i<=n;i++)
        for(R int j=m-1;j>=1;j--)
            if(mp[i][j]!=mp[i][j+1])
                r[i][j]=r[i][j+1];
    for(R int i=1;i<=n;i++){
        for(R int j=1;j<=m;j++){
            if(i>1&&mp[i][j]!=mp[i-1][j]){
                l[i][j]=max(l[i][j],l[i-1][j]);
                r[i][j]=min(r[i][j],r[i-1][j]);
                up[i][j]=up[i-1][j]+1;
            }
            R int a=r[i][j]-l[i][j]+1;
            R int b=min(a,up[i][j]);
            ans1=max(ans1,b*b);
            ans2=max(ans2,a*up[i][j]);
        }
    }
    

    5.nim游戏

    tmp=0;
    read(n);
    for(R int i=1;i<=n;i++)
        read(x),tmp^=x;
    if(tmp)printf("Yes
    ");
    else printf("No
    ");
    

    6.线段树双lazy

    #define ls(o) o<<1
    #define rs(o) o<<1|1
    #define up(o) t[o]=(t[ls(o)]+t[rs(o)])%mod
    inline void build(R int o,R int l,R int r){
    	mul[o]=1;add[o]=0;
    	if(l==r){
    		t[o]=a[l]%mod;
    		return;
    	}
    	R int mid=(l+r)>>1;
    	build(ls(o),l,mid);
    	build(rs(o),mid+1,r);
    	up(o);
    }
    inline void push_down(R int o,R int l,R int r){
    	if(mul[o]!=1){
    		t[ls(o)]=(mul[o]*t[ls(o)])%mod;
    		t[rs(o)]=(mul[o]*t[rs(o)])%mod;
    		add[ls(o)]=(add[ls(o)]*mul[o])%mod;
    		add[rs(o)]=(add[rs(o)]*mul[o])%mod;
    		mul[ls(o)]=(mul[o]*mul[ls(o)])%mod;
    		mul[rs(o)]=(mul[o]*mul[rs(o)])%mod;
    		mul[o]=1;
    	}
    	R int mid=(l+r)>>1;
    	if(add[o]){
    		t[ls(o)]=(t[ls(o)]+add[o]*(mid-l+1))%mod;
    		t[rs(o)]=(t[rs(o)]+add[o]*(r-mid))%mod;
    		add[ls(o)]=(add[ls(o)]+add[o])%mod;
    		add[rs(o)]=(add[rs(o)]+add[o])%mod;
    		add[o]=0;
    	}
    }
    inline void update_add(R int o,R int nl,R int nr,R int l,R int r,R ll k){
    	if(nl<=l&&nr>=r){
    		t[o]=(t[o]+(r-l+1)*k)%mod;
    		add[o]=(add[o]+k)%mod;
    		return;
    	}
    	push_down(o,l,r);
    	R int mid=(l+r)>>1;
    	if(nl<=mid)update_add(ls(o),nl,nr,l,mid,k);
    	if(nr>mid)update_add(rs(o),nl,nr,mid+1,r,k);
    	up(o);
    }
    inline void update_mul(R int o,R int nl,R int nr,R int l,R int r,R ll k){
    	if(nl<=l&&nr>=r){
    		t[o]=t[o]*k%mod;
    		add[o]=add[o]*k%mod;
    		mul[o]=mul[o]*k%mod;
    		return;
    	}
    	push_down(o,l,r);
    	R int mid=(l+r)>>1;
    	if(nl<=mid)update_mul(ls(o),nl,nr,l,mid,k);
    	if(nr>mid)update_mul(rs(o),nl,nr,mid+1,r,k);
    	up(o);
    }
    

    最大子段和

    struct node{
        int lm,rm,sm,sum;
        void init(int x){
            lm=rm=sm=sum=x;
        }
        friend node operator + (node a,node b){
            node ans;
            ans.sum=a.sum+b.sum;
            ans.sm=max(max(a.sm,b.sm),a.rm+b.lm);
            ans.lm=max(a.lm,a.sum+b.lm);
            ans.rm=max(b.rm,b.sum+a.rm);
            return ans;
        }
    }t[N];
    

    7.有理数取余(附加快速幂)

    char A[N],B[N];
    ll a,b;
    inline ll ksm(R ll x,R ll y){
    	ll res=1;
    	while(y){
    		if(y&1)res=res*x%mod;
    		x=x*x%mod;
    		y>>=1;
    	}
    	return res;
    }
    int main(){
    	scanf("%s%s",A+1,B+1);
    	R int n=strlen(A+1);
    	R int m=strlen(B+1);
    	for(R int i=1;i<=n;i++)
    		a=(a*10+A[i]-'0')%mod;
    	for(R int i=1;i<=m;i++)
    		b=(b*10+B[i]-'0')%mod;
    	if(!b)printf("Angry!
    ");
    	else printf("%lld
    ",a*ksm(b,mod-2)%mod);
        return 0;
    }
    

    8.割点(割顶)

    inline void tarjan(R int x){
    	R int rd=0;
    	dfn[x]=low[x]=++num;
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(!dfn[xx]){
    			fa[xx]=fa[x];
    			tarjan(xx);
    			low[x]=min(low[x],low[xx]);
    			if(low[xx]>=dfn[x]&&x!=fa[x])cut[x]=1;
    			if(x==fa[x])rd++;
    		}
    		low[x]=min(low[x],dfn[xx]);
    	}
    	if(x==fa[x]&&rd>=2)cut[x]=1;
    }
    int main(){
    	read(n);read(m);
    	for(R int i=1,u,v;i<=m;i++)
    		read(u),read(v),add(u,v),add(v,u);
    	for(R int i=1;i<=n;i++)fa[i]=i;
    	for(R int i=1;i<=n;i++)
    		if(!dfn[i])tarjan(i);
    	R int now=0;
    	for(R int i=1;i<=n;i++)
    		if(cut[i])ans[++now]=i;
    	printf("%d
    ",now);
    	for(R int i=1;i<=now;i++)printf("%d ",ans[i]);
    	return 0;
    } 
    

    9.缩点

    inline void tarjan(R int x){
    	vis[x]=1;
    	sta[++top]=x;
    	dfn[x]=low[x]=++num;
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(!dfn[xx]){
    			tarjan(xx);
    			low[x]=min(low[x],low[xx]);
    		}
    		else if(vis[xx])low[x]=min(low[x],dfn[xx]);
    	}
    	if(dfn[x]==low[x]){
    		cnt++;
    		R int now=-1;
    		while(now!=x){
    			now=sta[top];
    			top--;
    			col[now]=cnt;
    			sum[cnt]+=val[now];
    			vis[now]=0;
    		}
    	}
    }
    

    10.裴蜀定理

    scanf("%d",&n);
    scanf("%d",&ans);
    ans=abs(ans);
    for(R int i=2;i<=n;i++){
        scanf("%d",&x);
        ans=gcd(ans,abs(x));
    }
    printf("%d",ans);
    

    11.负环

    inline bool spfa(R int s){
    	queue<int> q;
    	for(R int i=1;i<=n;i++)dist[i]=INF,vis[i]=0;
    	q.push(s);vis[s]=1;dist[s]=0;cnt[s]++;
    	while(!q.empty()){
    		R int x=q.front();q.pop();vis[x]=0;
    		cnt[x]++;
    		if(cnt[x]>=n)return 1;
    		for(R int i=h[x];i;i=edge[i].nex){
    			R int xx=edge[i].to;
    			if(dist[xx]>dist[x]+edge[i].dis){
    				dist[xx]=dist[x]+edge[i].dis;
    				if(!vis[xx]){
    					vis[xx]=1;
    					q.push(xx);
    				}
    			}
    		}
    	}
    	return 0;
    }
    

    11+.最短路计数

    while(!q.empty()){
        int x=q.front();q.pop();vis[x]=0;
        for(int i=h[x];i;i=edge[i].nex){
            int xx=edge[i].to;
            if(dist[xx]==dist[x]+edge[i].dis){
                ans[xx]+=ans[x];ans[xx]%=mod;
                if(!vis[xx]){
                    vis[xx]=1;
                    q.push(xx);
                }
            }
            if(dist[xx]>dist[x]+edge[i].dis){
                dist[xx]=dist[x]+edge[i].dis;
                ans[xx]=ans[x]%mod;
                if(!vis[xx]){
                    vis[xx]=1;
                    q.push(xx);
                }
            }
        }
    

    12.Dij堆优化

    struct HeapNode{
    	int u;ll d;
    	friend bool operator < (const HeapNode &a,const HeapNode &b){
    		return a.d>b.d;
    	}
    };
    priority_queue<HeapNode> q;
    inline void Dij(R int s){
    	for(R int i=1;i<=n;i++)dist[i]=INF,vis[i]=0;
    	q.push((HeapNode){s,0});dist[s]=0;
    	while(!q.empty()){
    		R int x=q.top().u;q.pop();
    		if(vis[x])continue;vis[x]=1;
    		for(R int i=h[x];i;i=edge[i].nex){
    			R int xx=edge[i].to;
    			if(dist[xx]>dist[x]+edge[i].dis){
    				dist[xx]=dist[x]+edge[i].dis;
    				q.push((HeapNode){xx,dist[xx]});
    			}
    		}
    	}
    }
    

    13.manacher

    scanf("%s",a);
    n=strlen(a);
    for(R int i=0;i<n;i++)s[i*2]='#',s[i*2+1]=a[i];
    n=2*n+1;s[n-1]='#';
    rl[0]=1;
    for(R int i=0;i<n;i++){
        if(i<=maxright)rl[i]=min(rl[center*2-i],maxright-i);
        else rl[i]=1; 
        while(s[i+rl[i]]==s[i-rl[i]]&&i+rl[i]<n&&i-rl[i]>=0)rl[i]++;
        if(i+rl[i]-1>maxright)maxright=i+rl[i]-1,center=i;
    }
    for(R int i=0;i<n;i++)ans=max(ans,rl[i]-1);
    

    14.KMP

    scanf("%s%s",s1+1,s2+1);
    l1=strlen(s1+1);
    l2=strlen(s2+1);
    R int j=0;
    nex[1]=0;
    for(R int i=2;i<=l2;i++){
        while(j&&s2[i]!=s2[j+1])j=nex[j];
        if(s2[i]==s2[j+1])j++;
        nex[i]=j;
    }
    j=0;
    for(R int i=1;i<=l1;i++){
        while(j&&s1[i]!=s2[j+1])j=nex[j];
        if(s1[i]==s2[j+1])j++;
        if(j==l2){
            printf("%d
    ",i-l2+1);
            j=nex[j];
        }
    }
    

    15.线性求逆元

    read(n);read(mod);
    a[1]=1;
    for(R int i=2;i<=n;i++)
        a[i]=(((-mod/i)*a[mod%i])%mod+mod)%mod;
    for(R int i=1;i<=n;i++)printf("%lld
    ",a[i]);
    

    阶乘及阶乘逆元

    fac[0]=fac[1]=1;
    for(R int i=2;i<=n;i++)fac[i]=(fac[i-1]*i)%mod;
    inv[n]=ksm(fac[n],mod-2);
    for(R int i=n-1;i>=0;i--)inv[i]=((i+1)*inv[i+1])%mod;
    

    16.prim堆优化

    struct node{
    	int v,w;
    	friend bool operator < (const node &a,const node &b){
    		return a.w>b.w;
    	}
    };
    vector<node> t[N];
    bool vis[N];
    ll ans;
    inline void prim(){
    	priority_queue<node> q;
    	while(!q.empty())q.pop();
    	ans=0;
    	for(R int i=1;i<=n;i++)vis[i]=0;
    	for(R int i=0;i<(int)t[1].size();i++)
    		q.push(t[1][i]);
    	vis[1]=1;
    	R int bian=n-1;
    	R node x;
    	while(bian--){
    		x=q.top();q.pop();
    		if(vis[x.v])
    			while(vis[x.v])
    				x=q.top(),q.pop();
    		ans=ans+x.w;
    		vis[x.v]=1;
    		for(R int i=0;i<t[x.v].size();i++)
    			if(!vis[t[x.v][i].v])
    				q.push(t[x.v][i]);
    	} 
    }
    int main(){
    	read(n);read(m);node x;
    	for(R int i=1,u,v,w;i<=m;i++){
    		read(u);read(v);read(w);
    		x.v=v;x.w=w;
    		t[u].push_back(x);
    		x.v=u;
    		t[v].push_back(x);
    	}
    	prim();
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    17.树上差分

    inline void dfs(R int x,R int f){
    	dep[x]=dep[f]+1;fa[x][0]=f;
    	for(R int i=1;(1<<i)<=dep[x];i++)
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(xx==f)continue;
    		dfs(xx,x);
    	}
    }
    inline int lca(R int x,R int y){
    	if(dep[x]>dep[y])swap(x,y);
    	for(R int i=20;i>=0;i--)
    		if(dep[x]<=dep[y]-(1<<i))y=fa[y][i];
    	if(x==y)return x;
    	for(R int i=20;i>=0;i--)
    		if(fa[x][i]!=fa[y][i])
    			x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    inline void search(R int x){
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(xx==fa[x][0])continue;
    		search(xx);
    		cnt[x]+=cnt[xx];
    	}
    }
    //边差分
    cnt[x]++;cnt[y]++;
    cnt[LCA]-=2;
    //点差分
    cnt[x]++;cnt[y]++;
    cnt[LCA]--;cnt[fa[LCA][0]]--;
    

    18.并查集

    inline int find(R int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
    inline void merge(R int x,R int y){fa[find(x)]=find(y);}
    

    19.左偏堆

    inline int merge(R int x,R int y){
    	if(x==0||y==0)return x+y;
    	if(val[x]>val[y]||(val[x]==val[y]&&x>y))swap(x,y);
    	ch[x][1]=merge(ch[x][1],y);
    	fa[ch[x][1]]=x;
    	if(dep[ch[x][0]]<dep[ch[x][1]])swap(ch[x][0],ch[x][1]);
    	dep[x]=dep[ch[x][1]]+1;
    	return x;
    }
    inline int find(R int x){
    	while(fa[x])x=fa[x];
    	return x;
    }
    inline void pop(R int x){
    	val[x]=-1;
    	fa[ch[x][0]]=fa[ch[x][1]]=0;
    	merge(ch[x][0],ch[x][1]);
    }
    int main(){
    	read(n);read(m);
    	dep[0]=-1;
    	for(R int i=1;i<=n;i++)read(val[i]);
    	while(m--){
    		R int opt,x,y,xx,yy;
    		read(opt);
    		if(opt==1){
    			read(x);read(y);
    			if(val[x]==-1||val[y]==-1)continue;
    			if(x==y)continue;
    			xx=find(x),yy=find(y);
    			merge(xx,yy);
    		}
    		else{
    			read(x);
    			if(val[x]==-1)puts("-1");
    			else{
    				y=find(x);
    				printf("%d
    ",val[y]);
    				pop(y);
    			}
    		}
    	}
    	return 0;
    }
    

    20.最小瓶颈路

    struct MST{
    	int u,v,w;
    	friend bool operator < (const MST &a,const MST &b){
    		return a.w<b.w;
    	}
    }t[N];
    inline void ins(R int u,R int v,R int w){
    	t[++num].u=u;
    	t[num].v=v;
    	t[num].w=w;
    }
    struct node{
    	int nex,to,dis;
    }edge[N<<1];
    inline void add(R int u,R int v,R int w){
    	edge[++tot].nex=h[u];
    	edge[tot].to=v;
    	edge[tot].dis=w;
    	h[u]=tot;
    }
    inline int find(R int x){return fat[x]==x?fat[x]:fat[x]=find(fat[x]);}
    inline void dfs(R int x,R int f,R int g){
    	dep[x]=dep[f]+1;
    	fa[x][0]=f;
    	mx[x][0]=g;
    	for(R int i=1;(1<<i)<=dep[x];i++)
    		fa[x][i]=fa[fa[x][i-1]][i-1],
    		mx[x][i]=max(mx[x][i-1],mx[fa[x][i-1]][i-1]);
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(xx==f)continue;
    		dfs(xx,x,edge[i].dis);
    	}
    }
    inline int get_ans(R int x,R int y){
    	R int res=0;
    	if(dep[x]>dep[y])swap(x,y);
    	for(R int i=20;i>=0;i--)
    		if(dep[x]<=dep[y]-(1<<i))
    			res=max(res,mx[y][i]),y=fa[y][i];
    	if(x==y)return res;
    	for(R int i=20;i>=0;i--)
    		if(fa[x][i]!=fa[y][i])
    			res=max(res,max(mx[x][i],mx[y][i])),
    			x=fa[x][i],y=fa[y][i];
    	res=max(res,max(mx[x][0],mx[y][0]));
    	return res;
    }
    int main(){
    	read(n);read(m);
    	for(R int i=1;i<=n;i++)fat[i]=i;
    	for(R int i=1,u,v,w;i<=m;i++)
    		read(u),read(v),read(w),ins(u,v,w);
    	sort(t+1,t+1+m);
    	for(R int i=1;i<=m;i++){
    		R int x=find(t[i].u);
    		R int y=find(t[i].v);
    		if(x!=y){
    			fat[x]=y;
    			add(x,y,t[i].w);
    			add(y,x,t[i].w);
    		}
    	}
    	dfs(1,0,0);
    	read(q);
    	while(q--){
    		R int x,y;
    		read(x);read(y);
    		if(find(x)!=find(y))puts("impossible");
    		else printf("%d
    ",get_ans(x,y));
    	}
    	return 0;
    }
    

    21.矩阵乘法(Fib)

    struct Mar{
        ll a[10][10];
        Mar(){memset(a,0,sizeof(a));}
    };
    Mar cheng(Mar a,Mar b){
        Mar c;
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
        return c;
    }
    Mar ksm(Mar x,ll y){
        Mar res=e;
        while(y){
            if(y&1)res=cheng(res,x);
            x=cheng(x,x);
            y>>=1;
        }
        return res;
    }
    

    22.中国剩余定理

    void exgcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1;y=0;return;
        }
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    } 
    ll msc(ll x,ll y,ll mod){
        ll ans=0;
        while(y){
            if(y&1)ans=(ans+x)%mod;
            x=x*2%mod;
            y>>=1;
        }
        return ans;
    }
    void China(){
        for(int i=1;i<=n;i++)N*=b[i];
        ll x,y;//所求的X是N/b[i]*y
        for(int i=1;i<=n;i++){
            ll m=N/b[i];
            exgcd(b[i],m,x,y);
            y=(y+b[i])%b[i];
            X=(X+msc(msc(a[i],m,N),y,N))%N;
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) b[i]=read();
        China();
        printf("%lld",(X+N)%N);
        return 0;
    }
    

    23数列分块(余数求和)

    int main(){
        read(n);read(k);
        ans=n*k;
        for(R ll l=1,r;l<=n;l=r+1){
            ll s=k/l;
            if(s!=0)r=min(k/s,n);
            else r=n;
            ans-=s*(r-l+1)*(l+r)/2;
        }
        printf("%lld",ans);
        return 0;
    }
    

    24.线性基

    void insert(long long x){
        for(int i=63;i>=0;i--){
            if(x&(1LL<<i)){
                if(!p[i]){
                    p[i]=x;break;
                }
                else x^=p[i];
            }
        }
    }
    int main(){
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            insert(a[i]);
        }
        for(int i=63;i>=0;i--){
            if((ans^p[i])>ans)ans^=p[i];
        }
        printf("%lld
    ",ans);
        return 0;
    } 
    

    25.逆序对

    inline void msort(R int l,R int r){
        if(l==r)return;
        R int mid=(l+r)>>1;
        msort(l,mid);msort(mid+1,r);
        R int i=l,j=mid+1,k=l;
        while(i<=mid&&j<=r)
            if(a[i]<=a[j])
                b[k]=a[i],k++,i++;
            else
                b[k]=a[j],k++,j++,ans+=(mid-i+1);
        while(i<=mid)
            b[k]=a[i],i++,k++;
        while(j<=r)
            b[k]=a[j],j++,k++;
        for(R int i=l;i<=r;i++)
            a[i]=b[i];
    }
    

    26.高精

    struct big{
    	int a[N];
    }x,y,ed,one;
    big operator + (big a,big b){
    	big c;
    	memset(c.a,0,sizeof(c.a));
    	int len=max(a.a[0],b.a[0]);
    	for(int i=1;i<=len;i++)c.a[i]=a.a[i]+b.a[i];
    	for(int i=1;i<=len;i++)
    		if(c.a[i]>=10){
    			c.a[i+1]+=c.a[i]/10;
    			c.a[i]%=10;
    		}
    	if(c.a[len+1])len++;
    	c.a[0]=len;
    	return c;
    }
    big operator - (big a,big b){
    	big c;
    	memset(c.a,0,sizeof(c.a));
    	int len=max(a.a[0],b.a[0]);
    	for(R int i=1;i<=len;i++)c.a[i]=a.a[i]-b.a[i];
    	for(R int i=1;i<=len;i++){
    		if(c.a[i]<0){
    			c.a[i+1]--;
    			c.a[i]+=10;
    		}
    	}
    	while(!c.a[len])len--;
    	c.a[0]=len;
    	return c;
    }
    big operator / (big a,int x){
    	big c;
    	memset(c.a,0,sizeof(c.a));
    	int len=0,tmp=0;
    	for(R int i=a.a[0];i>=1;i--){
    		tmp=tmp*10+a.a[i];
    		if(tmp>=x){
    			c.a[++len]=tmp/x;
    			tmp%=x;
    		}
    		else c.a[++len]=0;
    	}
    	for(R int i=1;i<=len;i++)w[i]=c.a[len-i+1];
    	for(R int i=1;i<=len;i++)c.a[i]=w[i];
    	c.a[0]=len;
    	return c;
    }
    inline void print(big x){
    	if(x.a[0]==0)printf("0");
    	for(int i=x.a[0];i>=1;i--)
    		printf("%d",x.a[i]);
    }
    

    27.二分图

    inline int find(R int x){
        for(R int i=1;i<=n;i++){
            if(!vis[i]&&mp[x][i]){
                vis[i]=1;
                if(!to[i]||find(to[i])){
                    to[i]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    for(R int i=1;i<=m;i++){
       memset(vis,0,sizeof(vis));
       if(find(i))ans++;
    }
    

    28.模拟退火

    void SA(){
        double T = 2333.0;
        double xx = x,yy = y;
        while(T > 1e-16){
            double vx = xx + T * (rand() * 2 - RAND_MAX),vy = yy + T * (rand() * 2 - RAND_MAX);
            double res = calc(vx,vy) - calc(xx,yy);
            if(res < 0){
            	x = xx = vx,y = yy = vy;
        	}
        	else if(exp(-res/ T) * RAND_MAX > rand())xx = x,yy = y;
        	T = T * 0.9982;
        }
    }
    

    29.Trie树

    void insert(char *s,int rt){
        for(int i=0;s[i];i++){
            int v=s[i]-'a';
            if(!trie[rt][v]) trie[rt][v]=++tot;
            rt=trie[rt][v];
        }
    }
    int find(char *s,int rt){
        for(int i=0;s[i];i++){
            int v=s[i]-'a';
            if(!trie[rt][v])return 0;
            rt=trie[rt][v];
        }
        sum[rt]++;
        return sum[rt];
    }
    

    01 Trie树

    inline void insert(R int x,R int rt){
        for(R int i=1<<30;i;i>>=1){
            bool c=x&i;
            if(!trie[rt][c])trie[rt][c]=++num;
            rt=trie[rt][c];
        }
    }
    inline int query(R int x,R int rt){
        R int ans=0;
        for(R int i=1<<30;i;i>>=1){
            bool c=x&i;
            if(trie[rt][c^1])ans+=i,rt=trie[rt][c^1];
            else rt=trie[rt][c];
        }
        return ans;
    }
    

    30.LCS && LIS

    //LCS
    for(R int i=1;i<=n;i++)
        for(R int j=1;j<=m;j++)
            dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]+(a[i]==b[j])));
    printf("%d
    ",dp[n][m]);
    //LIS
    read(n);read(k);
    for(R int i=1;i<=n;i++)read(b[i]);
    for(R int i=1;i<=k-1;i++)
        if(b[i]<b[k])a[++tot]=b[i];
    a[++tot]=b[k];
    for(R int i=k+1;i<=n;i++)
        if(b[i]>b[k])a[++tot]=b[i];
    low[1]=a[1];ans=1;
    for(R int i=2;i<=tot;i++){
        if(a[i]>=low[ans])low[++ans]=a[i];
        else low[lower_bound(low+1,low+1+ans,a[i])-low]=a[i];
    }
    printf("%d
    ",ans);
    //统计方案数
    for(R int i=1;i<=n;i++){
        dp[i]=1;
        for(R int j=1;j<i;j++)
            if(a[j]>a[i])dp[i]=max(dp[i],dp[j]+1);
        ans=max(ans,dp[i]);
    }
    for(R int i=1;i<=n;i++){
        if(dp[i]==1)cnt[i]=1;
        for(R int j=1;j<i;j++){
            if(a[j]==a[i]&&dp[i]==dp[j])cnt[j]=0;
            if(a[j]>a[i]&&dp[i]==dp[j]+1)cnt[i]+=cnt[j];
        }
    }
    for(R int i=1;i<=n;i++)pos+=cnt[i]*(dp[i]==ans);
    printf("%d %d
    ",ans,pos);
    

    31.对顶堆

    priority_queue<int> q1;
    priority_queue<int,vector<int>,greater<int> > q2;
    inline void ins(R int x){
        if(x>q1.top())q2.push(x);
        else q1.push(x);
    }
    inline void query(){
        int pos=q1.size()+q2.size();
        while(abss(q1.size()-q2.size())>1){
            if(q1.size()>q2.size())q2.push(q1.top()),q1.pop();
            else q1.push(q2.top()),q2.pop();
        }
        if(pos&1){
            if(q1.size()>q2.size())printf("%d
    ",q1.top());
            else printf("%d
    ",q2.top());
        }
        else {
            printf("%d
    ",min(q1.top(),q2.top()));
        }
    }
    

    32.康拓展开

    inline ll contor(ll c[]){
        ll ans=0;
        for(R int i=1;i<=n;i++){
            ll sum=0;
            for(R int j=i+1;j<=n;j++)
                if(c[i]>c[j])sum++;
            ans+=sum*fac[n-i];
        }
        return ans+1;
    }
    inline ll revcontor(ll x){
        memset(vis,0,sizeof(vis));
        x--;ll j;
        for(R int i=1;i<=n;i++){
            ll t=x/fac[n-i];
            for(j=1;j<=n;j++){
                if(!vis[j]){
                    if(!t)break;
                    t--;
                }
            }
            printf("%lld ",j);
            vis[j]=1;
            x%=fac[n-i];
        }
        printf("
    ");
    }
    

    33.树链剖分

    //---------------------线段树--------------------------- 
    void build(int o,int l,int r){
    	if(l==r){
    		t[o]=a[tid[l]];  //guo
    		tag[o]=0;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls(o),l,mid);
    	build(rs(o),mid+1,r);
    	up(o);
    }
    
    void chuan(int o,int l,int r,int k){
    	tag[o]+=k;
    	t[o]+=k*(r-l+1);
    	t[o]%=mod;
    }
    void push_down(int o,int l,int r){
    	int mid=(l+r)>>1;
    	chuan(ls(o),l,mid,tag[o]);
    	chuan(rs(o),mid+1,r,tag[o]);
    	tag[o]=0;
    	up(o);
    }
    
    void change(int o,int nl,int nr,int l,int r,int k){
    	if(nl<=l&&nr>=r){
    		t[o]+=k*(r-l+1);
    		t[o]%=mod;
    		tag[o]+=k;
    		tag[o]%=mod;
    		return;
    	}
    	push_down(o,l,r);
    	int mid=(l+r)>>1;
    	if(nl<=mid)change(ls(o),nl,nr,l,mid,k);
    	if(nr>mid)change(rs(o),nl,nr,mid+1,r,k);
    	up(o);
    }
    
    int query(int o,int nl,int nr,int l,int r){
    	int ans=0;
    	if(nl<=l&&nr>=r)return t[o]%mod;
    	int mid=(l+r)>>1;
    	push_down(o,l,r);
    	if(nl<=mid)ans=(ans+query(ls(o),nl,nr,l,mid))%mod;
    	if(nr>mid) ans=(ans+query(rs(o),nl,nr,mid+1,r))%mod;
    	return ans%mod;
    }
    //---------------------线段树--------------------------- 
    struct node{
    	int nex,to;
    }edge[N<<1];
    
    void add(int u,int v){
    	edge[++tot].nex=h[u];
    	edge[tot].to=v;
    	h[u]=tot;
    }
    //求 fa,dep,size,son(重儿子) 
    void dfs1(int x,int f,int depth){
    	fa[x]=f;dep[x]=depth;siz[x]=1;
    	for(int i=h[x];i;i=edge[i].nex){
    		int xx=edge[i].to;
    		if(dep[xx])continue;
    		dfs1(xx,x,depth+1);
    		siz[x]+=siz[xx];
    		if(son[x]==-1||siz[xx]>siz[son[x]])son[x]=xx;
    	}
    }
    //求 dfn,tid,top; 
    void dfs2(int x,int tp){
    	dfn[x]=++num;tid[num]=x;top[x]=tp;
    	if(son[x]==-1)return;
    	dfs2(son[x],tp);
    	for(int i=h[x];i;i=edge[i].nex){
    		int xx=edge[i].to;
    		if(dfn[xx])continue;
    		dfs2(xx,xx);
    	}
    }
    
    int ask_path(int x,int y){
    	int ans=0;
    	int fx=top[x],fy=top[y];
    	while(fx!=fy){
    		if(dep[fx]>dep[fy]){
    			ans+=query(1,dfn[fx],dfn[x],1,n);
    			ans%=mod;
    			x=fa[fx];
    		}
    		else {
    			ans+=query(1,dfn[fy],dfn[y],1,n);
    			ans%=mod;
    			y=fa[fy];
    		}
    		fx=top[x];fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	ans+=query(1,dfn[x],dfn[y],1,n);
    	ans%=mod;
    	return ans%mod;
    } 
    
    void update(int x,int y,int z){
    	int fx=top[x],fy=top[y];
    	while(fx!=fy){
    		if(dep[fx]>dep[fy]){
    			change(1,dfn[fx],dfn[x],1,n,z);
    			x=fa[fx];
    		}
    		else {
    			change(1,dfn[fy],dfn[y],1,n,z);
    			y=fa[fy];
    		}
    		fx=top[x];fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	change(1,dfn[x],dfn[y],1,n,z);
    }
    //query(1,dfn[x],dfn[x]+siz[x]-1,1,n)子树操作
    

    34.倍增Floyed

    struct Mar{
        ll a[N][N];
        Mar(){memset(a,0x3f,sizeof(a));}
    };
    Mar e,ans;
    Mar cheng(R Mar a,R Mar b){
        Mar c; 
        for(R int k=1;k<=tot;k++)
            for(R int i=1;i<=tot;i++)	
                for(R int j=1;j<=tot;j++)
                    c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
        return c;
    }
    Mar ksm(R Mar x,ll y){
        ans=x;
        while(y){
            if(y&1)ans=cheng(ans,x);
            x=cheng(x,x);
            y>>=1;
        }
    }
    int main(){
        read(n);read(m);read(s);read(t);
        for(R int i=1,w,u,v;i<=m;i++){
            read(w);read(u);read(v);
            if(!vis[u])vis[u]=++tot;
            if(!vis[v])vis[v]=++tot;
            e.a[vis[u]][vis[v]]=e.a[vis[v]][vis[u]]=w;
        }
        ksm(e,n-1);
        printf("%lld
    ",ans.a[vis[s]][vis[t]]);
        return 0;
    }
    

    35.A*(K短路)

    int n,m,s,t,k,tot,ans;
    int h1[M],h2[M];
    struct bian{
    	int nex,to,val;
    }edge[M],E[M];
    struct node{
    	int f;//f=g+dist  估价函数 
    	int g;//到当前点的路径长度 
    	int from;
    	bool operator < (node a)const {
    		if(a.f==f)return g>a.g;
    		return f>a.f;
    	} 
    };
    void add(int u,int v,int w){
    	edge[++tot].nex=h1[u];
    	edge[tot].to=v;
    	edge[tot].val=w;
    	h1[u]=tot;
    	E[tot].nex=h2[v]; 
    	E[tot].to=u;
    	E[tot].val=w;
    	h2[v]=tot;
    }
    struct HeapNode{
    	int u,d;
    	bool operator < (const HeapNode & b) const {return d>b.d;}
    }; 
    int dist[M];
    bool vis[M];
    priority_queue<HeapNode> Q;
    void dij(int s){
    	for(int i=1;i<=n;i++)dist[i]=INF;
    	dist[s]=0; Q.push((HeapNode){s,0});
    	while(Q.size()){
    		int x=Q.top().u;Q.pop();
    		if(vis[x])continue; vis[x]=1;
    		for(int i=h2[x];i;i=E[i].nex){
    			int xx=E[i].to;
    			if(dist[xx]>dist[x]+E[i].val){
    				dist[xx]=dist[x]+E[i].val;
    				Q.push( (HeapNode){xx,dist[xx]});
    			}
    		}
    	}
    }
    int A_star(int s,int t,int k){
    	if(s==t) return 0;         //起点即为终点 
    	if(dist[s]==INF)return -1; //起点无联通 
    	priority_queue<node> q;    //优先队列搜索 
    	int cnt=0;                 //记录第X短路 
    	node tmp={0,0,0},to={0,0,0};
    	tmp.from=s;
    	tmp.f=tmp.g+dist[tmp.from];//估价函数 
    	q.push(tmp);
    	while(!q.empty()){
    		tmp=q.top();
    		q.pop();
    		if(tmp.from==t) cnt++; //到达终点 
    		if(cnt==k)return tmp.g;//现在已经是第K短路 
    		for(int i=h1[tmp.from];i;i=edge[i].nex){
    			to.from=edge[i].to;
    			to.g=tmp.g+edge[i].val;
    			to.f=to.g+dist[to.from];
    			q.push(to);
    		}
    	}
    	return -1;
    }
    
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		u=read();v=read();w=read(); 
    		add(u,v,w);
    	}
    	s=read();t=read();k=read();
    	dij(t);					 //反向边跑最短路 
    	ans=A_star(s,t,k);
    	printf("%d",ans); 
    	return 0;
    }
    

    end.对拍

    @echo off
    :loop
    echo noip2018 rp++
    
    data.exe>data.txt
    a.exe<data.txt>a.txt
    b.exe<data.txt>b.txt
    fc a.txt b.txt
    if not errorlevel 1 goto loop
    pause
    goto loop
    

    ex

    next_permutation(a+1,a+1+n);
    
  • 相关阅读:
    [Leetcode Weekly Contest]285
    [Leetcode Weekly Contest]286
    [Leetcode Weekly Contest]284
    [Leetcode Weekly Contest]287
    阿凡达机器人简介
    PS常用组合键
    PhotoshopCS6 后退多步
    如何卸载Creative Cloud?
    五月实际
    SSO 方案演进
  • 原文地址:https://www.cnblogs.com/ZAGER/p/9859932.html
Copyright © 2020-2023  润新知