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

    传送门

    (HMAPPY2)

    话说这题居然卡(scanf)的么???

    int T;cin>>T;
    while(T--){
    	cin>>n>>a>>b>>k;
    	puts(n/a+n/b-n/(a*b/__gcd(a,b))*2>=k?"Win":"Lose");
    }
    

    (CHEFING)

    咕咕

    int T;scanf("%d",&T);
    while(T--){
    	scanf("%d",&n),res=0;
    	fp(i,0,25)flag[i]=1;
    	while(n--){
    		scanf("%s",s+1);
    		fp(i,0,25)cnt[i]=0;
    		fp(i,1,strlen(s+1))cnt[s[i]-'a']=1;
    		fp(i,0,25)flag[i]&=cnt[i];
    	}
    	fp(i,0,25)res+=flag[i];
    	printf("%d
    ",res);
    }
    

    (DEPCHEF)

    咕咕咕

    int T;scanf("%d",&T);
    while(T--){
    	scanf("%d",&n),mx=-1;
    	fp(i,1,n)scanf("%d",&a[i]);a[0]=a[n],a[n+1]=a[1];
    	fp(i,1,n)scanf("%d",&d[i]);d[0]=d[n],d[n+1]=d[1];
    	fp(i,1,n)if(a[i-1]+a[i+1]<d[i])cmax(mx,d[i]);
    	printf("%d
    ",mx);
    }
    

    (MAGICJAR)

    咕咕咕咕

    int T;scanf("%d",&T);
    while(T--){
    	scanf("%d",&n),res=0;
    	fp(i,1,n)scanf("%d",&a[i]),res+=a[i]-1;
    	printf("%lld
    ",res+1);
    }
    

    (ARTBALAN)

    发现只与字母出现次数有关。枚举一下最后剩下(k)个字母,那么每种字母要剩(n/k)个,如果不选代价是(cnt_i),选了代价是(|cnt_i-n/k|),先假设全选,再找出(|cnt_i-n/k|-cnt_i)最小的(k)个加上就是了

    //minamoto
    #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 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;
    }
    int read(char *s){
    	R int len=0;R char ch;while(((ch=getc())>'Z'||ch<'A'));
    	for(s[++len]=ch;(ch=getc())>='A'&&ch<='Z';s[++len]=ch);
    	return s[len+1]='',len;
    }
    const int N=1e6+5;
    char s[N];int cnt[35],a[35],res,tmp,n;
    inline int abs(R int x){return x<0?-x:x;}
    int main(){
    //	freopen("testdata.in","r",stdin);
    	for(int T=read();T;--T){
    		n=read(s),res=n+1;
    		memset(cnt,0,104);
    		fp(i,1,n)++cnt[s[i]-'A'];
    		fp(k,1,26)if(n%k==0){
    			tmp=0;
    			fp(i,0,25)tmp+=cnt[i],a[i]=abs(n/k-cnt[i])-cnt[i];
    			sort(a,a+26);
    			fp(i,0,k-1)tmp+=a[i];
    			cmin(res,tmp>>1);
    		}
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    

    (MANRECT)

    先询问((0,0)),可以求出矩形左下角所在的那条副对角线,同理询问((0,inf),(inf,inf),(inf,0)),然后再求出左上角的对角线和右上角的对角线的交点横坐标(x)(有可能不是整数,那么下取整),此时询问((x,inf)),得到的必然是矩形上边界离(y=inf)这条直线的距离,然后就求出矩形右上角的(y)坐标了,剩下的代入方程就可以了

    话说为啥用(scanf)(printf)(T)啊???

    //minamoto
    #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)
    using namespace std;
    int read(){
        R int res,f=1;R char ch;
        while((ch=getchar())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getchar())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    inline int print(R int x,R int y){cout<<'Q'<<' '<<x<<' '<<y<<endl;fflush(stdout);return read();}
    const int inf=1e9;
    int a,b,c,d,t,x,y,xx,yy;
    int main(){
    //	freopen("testdata.in","r",stdin);
    	int T=read();
    	while(T--){
    		a=print(0,0),b=print(0,inf),c=print(inf,inf),d=print(inf,0);
    		if(0ll+b+c<inf)t=print(b+1,inf);else t=print((0ll+inf+b-c)>>1,inf);
    		yy=0ll+inf-t,xx=0ll+(inf<<1)-c-yy;
    		y=0ll+xx-inf+d,x=0ll+a-y;
    		cout<<'A'<<' '<<x<<' '<<y<<' '<<xx<<' '<<yy<<endl;
    		fflush(stdout);
    		read();
    	}
    	return 0;
    }
    

    (GUESSRT)

    最优策略应该是先排除最后一个不管,前面一直(12121212...),最后一个必选(1)

    证明的话……我瞎猜的一个结论你叫我证明……

    顺便注意如果刚开始(n>k)要先进行一次(2)操作令(nleq k)

    upd:去看了看官方题解,这个似乎应该反过来说,也就是如果只剩一个选(1),前面一直按照(21212121)的顺序,因为(21)的概率显然比(11)要大

    //minamoto
    #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)
    using namespace std;
    int read(){
        R int res,f=1;R char ch;
        while((ch=getchar())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getchar())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=6e4+5,P=1e9+7;
    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 n,m,k,res,tmp,inv[N];
    int main(){
    //	freopen("testdata.in","r",stdin);
    	inv[0]=inv[1]=1;fp(i,2,N-1)inv[i]=mul(P-P/i,inv[P%i]);
    	for(int T=read();T;--T){
    		n=read(),k=read(),m=read();
    		if(m==1){printf("%d
    ",inv[n]);continue;}
    		if(n>k)--m,n=(n-1)%k+1;
    		tmp=ksm(mul(n-1,inv[n]),(m+1)>>1);
    		res=add(P+1-tmp,(m&1^1)?mul(tmp,inv[n+k]):0);
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    

    (CHORCKIT)

    咕咕咕咕咕咕咕咕咕

    (challenge)不写了

    (XDCOMP)

    首先对于一个子树,只有它的异或和为(x)(0)才有分割成功的可能

    我们记(f_{u,0/1})表示对于(u)这棵子树,已经割掉的边为偶数/奇数的方案数,转移的时候,如果当前这条边不割,那么直接转移就是。只有当(sum_v)(其中(sum)表示子树异或和)为(0)(v)的子树里割掉的边为奇数条,或者(sum_v)(x)(v)的子树里割掉的边为偶数条,这一条边才允许被割掉。最后记得判一下整棵树的异或和

    //minamoto
    #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)
    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=1e5+5,P=1e9+7;
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:x;}
    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;
    }
    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 f[N][2],g[N][2],sum[N],n,x,res;
    void dfs(int u,int fa){
    	f[u][0]=1,f[u][1]=0;
    	go(u)if(v!=fa){
    		dfs(v,u),sum[u]^=sum[v];
    		g[u][0]=g[u][1]=0;
    		if(sum[v]==x){
    			upd(g[u][1],mul(f[u][0],f[v][0])),
    			upd(g[u][0],mul(f[u][1],f[v][0]));
    		}
    		if(sum[v]==0){
    			upd(g[u][1],mul(f[u][1],f[v][1])),
    			upd(g[u][0],mul(f[u][0],f[v][1]));
    		}
    		upd(g[u][0],mul(f[u][0],f[v][0])),
    		upd(g[u][0],mul(f[u][1],f[v][1])),
    		upd(g[u][1],mul(f[u][0],f[v][1])),
    		upd(g[u][1],mul(f[u][1],f[v][0]));
    		f[u][0]=g[u][0],f[u][1]=g[u][1];
    	}
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),x=read();
    	fp(i,1,n)sum[i]=read();
    	for(R int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
    	dfs(1,0);
    	if(sum[1]==x)upd(res,f[1][0]);
    	if(sum[1]==0)upd(res,f[1][1]);
    	printf("%d
    ",res);
    	return 0;
    }
    

    (MAXTAX)

    缩点之后跑个(dp)就可以了

    关于同一个联通块内,我们可以先(sort)一下,然后枚举有(i)个人会因为税款太高而愉悦,那么能收到的最大税款就是((cnt-i) imes b_{i+1})

    记得要求的是最大值,计算过程中不需要取模

    清零的时候我忘了(long long)(8)个字节然后计算的时候算错了orz

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define pb push_back
    #define ll long long
    #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 cmin(T&a,const T&b){return a>b?a=b,1:0;}
    template<class T>inline bool cmax(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;
    }
    const int N=2e5+5,M=5e5+5,P=1e9+21;
    struct eg{int v,nx;}e[M];int head[N],tot;
    inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
    vector<int>to[N],nod[N];int col[N],dfn[N],low[N],st[N],deg[N],top,cnt,tim;
    int q[N],a[N];ll f[N][205],tmp[205],res;
    void tarjan(int u){
    	dfn[u]=low[u]=++tim,st[++top]=u;
    	for(R int i=0,s=to[u].size(),v;i<s&&(v=to[u][i]);++i)
    		if(!dfn[v])tarjan(v),cmin(low[u],low[v]);
    		else if(!col[v])cmin(low[u],dfn[v]);
    	if(low[u]==dfn[u])
    		for(++cnt,st[top+1]=0;st[top+1]!=u;--top)
    			col[st[top]]=cnt,nod[cnt].pb(a[st[top]]);
    }
    int n,m,k;
    void clr(){
    	fp(i,1,n)vector<int>().swap(to[i]);
    	fp(i,1,cnt)vector<int>().swap(nod[i]);
    	memset(col,0,(n+1)<<2),memset(dfn,0,(n+1)<<2);
    	memset(deg,0,(cnt+1)<<2),memset(head,0,(cnt+1)<<2);
    	tot=cnt=top=tim=0;
    }
    void solve(){
    	int h=1,t=0,u;++cnt;
    	fp(i,1,cnt-1){
    		add(i,cnt),++deg[cnt];
    		if(!deg[i])q[++t]=i;
    		memset(f[i],0,(k+1)<<3);
    	}
    	memset(f[cnt],0,(k+1)<<3);
    	while(h<=t){
    		u=q[h++],sort(nod[u].begin(),nod[u].end());
    		fp(j,0,k)tmp[j]=f[u][j];
    		for(R int i=0,s=nod[u].size();i<s;++i)
    			fp(j,0,k-i)cmax(tmp[i+j],f[u][j]+1ll*(s-i)*nod[u][i]);
    		go(u){
    			fp(j,0,k)cmax(f[v][j],tmp[j]);
    			if(!--deg[v])q[++t]=v;
    		}
    	}
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	for(int T=read();T;--T){
    		n=read(),m=read(),k=read();
    		fp(i,1,n)a[i]=read();
    		for(R int i=1,u,v;i<=m;++i)u=read(),v=read(),to[u].pb(v);
    		fp(i,1,n)if(!dfn[i])tarjan(i);
    		fp(u,1,n)for(R int i=0,s=to[u].size(),v;i<s&&(v=to[u][i]);++i)
    			if(col[u]!=col[v])add(col[u],col[v]),++deg[col[v]];
    		solve();
    		res=0;
    		fp(i,0,k)cmax(res,f[cnt][i]);
    		printf("%lld
    ",res%P);
    		clr();
    	}
    	return 0;
    }
    

    (TRDST)

    我怎么又把点分给忘了→_→

    首先在每一个点处是可以二分答案的,那么我们现在的问题转化为求到它的距离大于(mid)的点数,也可以转化为数到它的距离小于等于(mid)的点数

    到某个顶点距离小于等于(k)的点数……这就是个点分树的经典应用了,我觉得代码比我讲得清楚所以建议自行看代码理解

    //minamoto
    #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;}
    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;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    }
    const int N=1e5+5,M=3e6+5;
    inline int min(R int x,R int y){return x<y?x:y;}
    int pool[M],*pp=pool;
    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;}
    struct Eg{int sz,nx,d,sgn,*c;}E[M];int Head[N],tc;
    int sz[N],mx[N],dep[N],fa[N],q[N],vis[N],size,rt;
    int n,a[N];
    void findrt(int u,int fa){
    	sz[u]=1,mx[u]=0;
    	go(u)if(v!=fa&&!vis[v])findrt(v,u),sz[u]+=sz[v],cmax(mx[u],sz[v]);
    	cmax(mx[u],size-sz[u]);
    	if(mx[u]<mx[rt])rt=u;
    }
    void dfs(int u,int sgn,int d){
    	int h=1,t=0;q[++t]=u,dep[u]=d,fa[u]=0;
    	while(h<=t){
    		u=q[h++],++pp[dep[u]];
    		go(u)if(!vis[v]&&v!=fa[u])q[++t]=v,dep[v]=dep[u]+1,fa[v]=u;
    	}
    	int len=dep[q[t]];
    	fp(i,1,t)u=q[i],E[++tc]={len,Head[u],dep[u],sgn,pp},Head[u]=tc;
    	fp(i,1,len)pp[i]+=pp[i-1];
    	pp+=len+1;
    }
    void solve(int u){
    	vis[u]=1,dfs(u,1,0);
    	int s=size;
    	go(u)if(!vis[v]){
    		dfs(v,-1,1);
    		rt=0,size=sz[v]>sz[u]?s-sz[u]:sz[v],findrt(v,0);
    		solve(rt);
    	}
    }
    int calc(int d,int u){
    	int res=0;
    	for(R int i=Head[u];i;i=E[i].nx)
    		if(d>=E[i].d)res+=E[i].c[min(d-E[i].d,E[i].sz)]*E[i].sgn;
    	return n-res;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	fp(i,1,n)a[i]=read();
    	for(R int i=1,u,v;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);
    	mx[0]=n+1,rt=0,size=n,findrt(1,0),solve(rt);
    	int l,r,mid,ans;
    	fp(i,1,n){
    		l=0,r=n-1;
    		while(l<=r)mid=(l+r)>>1,(calc(mid,i)>=a[i])?(ans=mid,l=mid+1):r=mid-1;
    		print(ans);
    	}
    	return Ot(),0;
    }
    
  • 相关阅读:
    【笔记】求数据前n个主成分以及对高维数据映射为低维数据
    使用sklearn中的fetch_mldata的错误情况以及可能可行的解决方法
    【笔记】求数据的对应主成分PCA(第一主成分)
    【笔记】主成分分析法PCA的原理及计算
    【笔记】如何确定梯度计算的准确性以及调试梯度下降法
    【笔记】随机梯度下降法
    【笔记】线性回归中的梯度下降法(实现以及向量化并进行数据归一化)
    AttributeError: module 'numpy' has no attribute 'num'
    灵雀云CTO陈恺:从“鸿沟理论”看云原生,哪些技术能够跨越鸿沟?
    容器云在证券行业的探索与实践
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10721322.html
Copyright © 2011-2022 走看看