zoukankan      html  css  js  c++  java
  • Code Chef JUNE Challenge 2019题解

    题面

    (SUMAGCD)

    先去重,易知答案一定是一个数单独一组剩下的一组,前缀后缀(gcd)一下就行了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int N=1e5+5;
    int a[N],suf[N],Pre[N],n,T,mx;
    int main(){
    	for(scanf("%d",&T);T;--T){
    		scanf("%d",&n),mx=0;
    		fp(i,1,n)scanf("%d",&a[i]);
    		sort(a+1,a+1+n),n=unique(a+1,a+1+n)-a-1;
    		if(n==1){printf("%d
    ",a[1]<<1);continue;}
    		Pre[0]=0;fp(i,1,n)Pre[i]=__gcd(a[i],Pre[i-1]);
    		suf[n+1]=0;fd(i,n,1)suf[i]=__gcd(suf[i+1],a[i]);
    		fp(i,1,n)cmax(mx,a[i]+__gcd(Pre[i-1],suf[i+1]));
    		printf("%d
    ",mx);
    	}
    	return 0;
    }
    

    (CHFING)

    (1)(k-1)肯定(gg),剩下的放到模(k)意义下,共有(k)个点,然后(n-1)条边,第(i)条边可以从(c)((c+k+i)\%k),设(dis_c)表示到(c)点的最短路,那么(dis_c+p imes k)都是能被标识的,剩下的不行。然后再仔细讨论一下就行了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    int T,res,p;ll n,k;
    const int P=1e9+7;
    inline int calc(R int x){return (1ll*x*(x+1)>>1)%P;}
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    	return res;
    }
    int main(){
    	for(scanf("%d",&T);T;--T){
    		scanf("%lld%lld",&n,&k),p=(k-1)/(n-1)%P,n%=P,k%=P;
    		res=add(mul(calc(p),n-1),mul(p+1,dec(k-1,mul(p,n-1))));
    		res=add(res,P);
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    

    (LENTMO)

    分情况讨论,如果(k=n)只有操作或不操作,如果(k)为奇数等价于(k=1),为偶数等价于(k=2)

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    int a[N],k,n,x,T;ll res,mx,sum[N];
    int main(){
    	for(scanf("%d",&T);T;--T){
    		scanf("%d",&n),mx=res=0;
    		fp(i,1,n)scanf("%d",&a[i]);
    		scanf("%d%d",&k,&x);
    		fp(i,1,n)res+=a[i],a[i]=(a[i]^x)-a[i];
    		sort(a+1,a+1+n);sum[n+1]=0;
    		fd(i,n,1)sum[i]=sum[i+1]+a[i];
    		if(k==n)cmax(mx,sum[1]);
    		else if(k&1)fp(i,1,n)cmax(mx,sum[i]);
    		else for(R int i=n-1;i>0;i-=2)cmax(mx,sum[i]);
    		printf("%lld
    ",res+mx);
    	}
    	return 0;
    }
    

    (INTRPATH)

    首先两条路径有交说明其中一个(LCA)在另一个上面。如果((a,b))((u,v))交于(w)上,(w)必定是(LCA(a,b))(LCA(u,v))

    树剖,对于(w)(LCA(a,b))的情况,每个节点上记录不同时经过(u)(u)的重儿子的简单路径的条数,然后做个前缀和。跳到另一条重链上的时候特殊处理一下,(LCA)上特殊处理一下

    对于(w)(LCA(u,v))的情况,计算一下跨过这棵子树的路径条数就可以了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    typedef long long ll;
    const int N=3e5+5;
    struct eg{int v,nx;}e[N<<1];int head[N],tot;
    inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
    int dfn[N],rk[N],sz[N],fa[N],dep[N],top[N],son[N];ll f[N],g[N],sum[N];
    int n,tim,q,T;
    inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
    void dfs1(int u){
    	sz[u]=1,dep[u]=dep[fa[u]]+1,f[u]=1,son[u]=0;
    	go(u)if(v!=fa[u]){
    		fa[v]=u,dfs1(v),f[u]+=1ll*sz[v]*sz[u],sz[u]+=sz[v];
    		if(sz[v]>sz[son[u]])son[u]=v;
    	}
    	g[u]=1ll*(sz[u]-sz[son[u]])*sz[son[u]],f[u]-=g[u];
    }
    void dfs2(int u,int t){
    	top[u]=t,sum[dfn[u]=++tim]=f[u];
    	if(!son[u])return;dfs2(son[u],t);
    	go(u)if(v!=fa[u]&&v!=son[u])dfs2(v,v);
    }
    int jump(int u,int lca){
    	int tmp=0;
    	while(top[u]!=top[lca])tmp=top[u],u=fa[tmp];
    	return sz[u==lca?tmp:son[lca]];
    }
    ll query(int u,int v){
    	if(u==v)return f[u]+g[u]+1ll*sz[u]*(n-sz[u]);
    	ll res=0;int x=u,y=v,lca,si;ll s;
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		u=fa[top[u]];
    	}
    	lca=dep[u]<dep[v]?u:v,u=x,v=y;
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		res+=sum[dfn[u]]-sum[dfn[top[u]]-1],u=top[u];
    		if(fa[u]!=lca)res+=g[fa[u]]-1ll*sz[u]*(sz[fa[u]]-sz[u]);
    		u=fa[u];
    	}
    	if(dep[u]<dep[v])swap(u,v);
    	res+=sum[dfn[u]]-sum[dfn[v]];
    	u=x,v=y,x=y=0;
    	if(u!=lca)res+=g[u],x=jump(u,lca);
    	if(v!=lca)res+=g[v],y=jump(v,lca);
    	s=f[lca]+g[lca],si=sz[lca],s-=1ll*x*(si-x),si-=x,s-=1ll*y*(si-y);
    	res+=s,res+=1ll*(sz[lca]-x-y)*(n-sz[lca]);
    	return res;
    }
    inline void clr(){memset(head,0,(n+1)<<2),memset(fa,0,(n+1)<<2),tot=tim=0;}
    int main(){
    //	freopen("testdata.in","r",stdin);
    	for(T=read();T;--T){
    		n=read(),q=read();
    		for(R int i=1,u,v;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);
    		dfs1(1),dfs2(1,1);
    		fp(i,1,n)sum[i]+=sum[i-1];
    		for(R int u,v;q;--q)u=read(),v=read(),printf("%lld
    ",query(u,v));
    		clr();
    	}
    	return 0;
    }
    

    (COOLCHEF)

    某位大佬:复杂度算啥能过就行

    简单来说就是用(vector)存下每个数的出现位置,然后每一个询问暴力二分就可以了……我也不知道为什么能过……唯一的剪枝就是把总共出现次数只有一次的去掉……

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=3e5+5,P=1e9+7;
    inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    	return res; 
    }
    vector<int>pos[N];int top,n,q,ans,m;
    int fac[N],ifac[N],b[N],a[N],sz[N],bg[N],ed[N],st[N];
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),q=read();
    	fp(i,1,n)a[i]=b[i]=read();
    	fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
    	ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
    	sort(b+1,b+1+n),m=unique(b+1,b+1+n)-b-1;
    	fp(i,1,n)a[i]=lower_bound(b+1,b+1+m,a[i])-b,pos[a[i]].push_back(i);
    	fp(i,1,m)if(pos[i].size()>1)
    		st[++top]=i,bg[top]=pos[i].front(),ed[top]=pos[i].back();
    	for(R int l1,l2,r1,r2,l,r,c;q;--q){
    		l1=read(),l2=read(),r1=read(),r2=read();
    		l=(1ll*l1*ans+l2)%n+1,r=(1ll*r1*ans+r2)%n+1;
    		if(l>r)swap(l,r);
    		ans=1;
    		fp(i,1,top)if(bg[i]<=r&&ed[i]>=l){
    			c=upper_bound(pos[st[i]].begin(),pos[st[i]].end(),r)
    			 -lower_bound(pos[st[i]].begin(),pos[st[i]].end(),l);
    			ans=mul(ans,ifac[c]);
    		}
    		ans=mul(ans,fac[r-l+1]);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    (COUNTIT)

    为了方便把前(n)个数记为(a_i),后(m)个数记为(b_i)

    可以证明,当且仅当(max(a_i)=max(b_i))一定是一组合法解(如果不想看证明的可以直接跳过)

    必要性很显然。对于充分性,假设(a_i)(b_i)的最大值都只有一个,那么把除了这一行一列之外的其他数都设为(1),这一行一列的数调整到满足对应行列的需求。如果有多个最大值同理

    所以答案就是

    [sum_{i=1}^kleft(i^n-(i-1)^n ight)(i^m-(i-1)^m) ]

    后面展开是一个(n+m)次多项式,前缀和是一个(n+m+1)次多项式,拉格朗日插值就行了

    代码还没调出来再等等

    好吧原来是拉格朗日插值打错了……

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    const int P=1e9+7;
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
        R int res=1;
        for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
        return res;
    }
    const int N=5e5+5;
    int fn[N],fm[N],f[N],fac[N],ifac[N],Pre[N],suf[N],n,m,p,T,c;
    int Lagrange(int n,int k){
    	if(k<=n)return f[k];
    	Pre[0]=1;fp(i,1,n)Pre[i]=mul(Pre[i-1],k-i);
    	suf[n+1]=1;fd(i,n,1)suf[i]=mul(suf[i+1],k-i);
    	int res=0,ty=(n&1)?1:P-1;
    	fp(i,1,n)upd(res,1ll*f[i]*ty%P*Pre[i-1]%P*suf[i+1]%P*ifac[i-1]%P*ifac[n-i]%P),ty=P-ty;
    	return res;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	int t=2e5+10;
    	fac[0]=ifac[0]=1;fp(i,1,t)fac[i]=mul(fac[i-1],i);
    	ifac[t]=ksm(fac[t],P-2);fd(i,t-1,1)ifac[i]=mul(ifac[i+1],i+1);
    	for(scanf("%d",&T);T;--T){
    		scanf("%d%d%d",&n,&m,&p),c=n+m+5;
    		fn[0]=fm[0]=0;
    		fp(i,1,c)fn[i]=ksm(i,n);
    		fp(i,1,c)fm[i]=ksm(i,m);
    		fp(i,1,c)f[i]=mul(dec(fn[i],fn[i-1]),dec(fm[i],fm[i-1]));
    		fp(i,1,c)upd(f[i],f[i-1]);
    		printf("%d
    ",Lagrange(c,p));
    	}
    }
    

    (FGTREE)

    七月月赛都开了我才补完六月的……

    我们对于(dfs)序从小到大考虑,维护一个栈,表示的是从根节点到当前节点的这条链,对于新的节点,如果还在这条链上就加入,否则说明之前有一些节点可以出栈了,那么就可以顺便更新左边界和他们的父亲

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    const int N=105;
    int fa[N],l[N],st[N],top,n,T;
    bool ask(int x,int l,int r){
    	printf("Q %d %d %d
    ",x,l,r),fflush(stdout);
    	char s[5];scanf("%s",s);return s[0]=='Y'; 
    } 
    int main(){
    	for(scanf("%d",&T);T;--T){
    		scanf("%d",&n),top=0;
    		memset(fa,-1,(n+1)<<2);
    		fp(i,1,n){
    			int las=0;
    			while(top&&ask(st[top],l[st[top]],i-1)){
    				if(las)fa[las]=st[top];
    				las=st[top--];
    			}
    			las?(fa[las]=i,l[i]=l[las]):l[i]=i;
    			st[++top]=i;
    		}
    		while(top>1)fa[st[top]]=st[top-1],--top;
    		putchar('A');
    		fp(i,1,n)printf(" %d",fa[i]);
    		puts(""),fflush(stdout);
    	}
    	return 0;
    }
    
  • 相关阅读:
    使用iptables禁止外网访问tomcat的8080端口
    解决ie浏览器下载apk或ipa变为zip
    'ᄈ'
    centos上安装grafana
    vertica单节点故障恢复 Startup Failed, ASR Required
    vertica审计日志
    centos安装nginx1.17.9
    centos上nginx转发tcp请求
    centos 安装mysql8.0.16
    centos下导出docx为html
  • 原文地址:https://www.cnblogs.com/yuanquming/p/11116926.html
Copyright © 2011-2022 走看看