zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 010

    AtCoder Grand Contest 010

    A - Addition

    翻译

    黑板上写了(n)个正整数,每次会擦去两个奇偶性相同的数,然后把他们的和写会到黑板上,问最终能否只剩下一个数。

    题解

    洛谷认为此题过水,已被隐藏。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int main()
    {
    	int n=read(),s=0;while(n--)s+=read()&1;
    	puts((s&1)?"NO":"YES");return 0;
    }
    

    B - Boxes

    翻译

    (n)个盒子排成了一圈,第(i)个盒子里有(a_i)个石头,每次可以选择一个盒子,假定它是(i)号,那么对于(j=[1,n]),第((i+j))号盒子会被丢掉(j)个石头,特别的,第(i+n)个盒子就是第(i)个盒子。问最终能否让所有盒子都变为空盒子。

    题解

    我表示不会做。

    首先通过所有元素之和可以很容易计算出总共减了多少次。现在考虑相邻两项之间的差,设总共减了(S)次,在(i)位置减了(x)次。那么可以知道(a_i-a_{i+1}=x*(n-1)-S)。这样子可以很容易的解出所有的(x)来,最后再(check)一下是否合法即可。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAX 100100
    #define ll long long
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,a[MAX];
    ll v[MAX],S,s,tot;
    int main()
    {
    	n=read();s=1ll*n*(n+1)/2;
    	for(int i=1;i<=n;++i)S+=(a[i]=read());a[n+1]=a[1];
    	if(n==1){puts("YES");return 0;}
    	if(S%s){puts("NO");return 0;}
    	S/=s;
    	for(int i=1;i<=n;++i)
    	{
    		v[i]=a[i]-a[i+1]+S;
    		if(v[i]%n||v[i]<0){puts("NO");return 0;}
    		tot+=v[i]/n;
    	}
    	if(tot!=S)puts("NO");else puts("YES");
    	return 0;
    }
    

    C - Cleaning

    翻译

    给定一棵树,每个点上有若干个石头,每次可以选择两个叶子节点,将路径上所有的点全部丢掉一块石头,问能否丢掉所有石头。

    题解

    考虑从叶子开始向上依次满足。如果一个点上有(a_i)个石子,那么它的叶子节点中的路径要达到这个点以及它的父亲总共(a_i)次。剩下的显然不能够出子树,只能够自己在子树内部匹配,显然子树内部每匹配一对点,那么它出去路径的总数就会减少(2)。对于每一个点,首先计算它的子树中最多能够出去的点数,然后计算一下在当前点的最大匹配数,如果当前所有点都出去了还满足不了当前点显然无解,如果当前点能够匹配的全部匹配上了还比当前点多显然也无解,否则恰好当前点需要的数量的路径出去就好了。

    我怎么感觉乱搞,搞着搞着就过了呢???

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAX 100100
    #define ll long long
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    void WA(){puts("NO");exit(0);}
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1,dg[MAX];
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;++dg[u];}
    int n,a[MAX],rt;
    void dfs(int u,int ff)
    {
    	int mx=0;ll sum=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		dfs(v,u);mx=max(mx,a[v]);sum+=a[v];
    	}
    	if(dg[u]==1)return;
    	ll mn=min(sum/2,sum-mx);
    	if(a[u]>sum)WA();
    	else
    	{
    		if(sum-mn>a[u])WA();
    		else a[u]-=sum-a[u];
    	}
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	if(n==2){puts(a[1]==a[2]?"YES":"NO");return 0;}
    	for(int i=1;i<n;++i)
    	{
    		int u=read(),v=read();
    		Add(u,v);Add(v,u);
    	}
    	for(int i=1;i<=n;++i)
    		if(dg[i]>1){dfs(rt=i,0);break;}
    	if(a[rt])WA();else puts("YES");
    	sreturn 0;
    }
    

    D - Decrementing

    翻译

    见洛谷

    题解

    先考虑简单情况,如果不考虑除去(gcd),那么胜负情况之和奇偶性相关。现在加上(gcd),如果(gcd)是一个奇数显然对于答案也没有影响。那么唯一对于答案有影响的只有(gcd)是一个偶数。显然如果有奇数个偶数的话,显然一定可以控制局面保证永远让自己赢。否则的话考虑先手能够改变一个数,使得自己能赢,然后我们并不知道是否可行,但是我们知道先手一定要去改这个数,所以递归算一下即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define MAX 100100
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,s,a[MAX];
    bool calc(int p)
    {
    	int s=0,mn=1e9;
    	for(int i=1;i<=n;++i)s+=a[i]&1,mn=min(mn,a[i]);
    	if((n-s)&1)return p;
    	if(s>1||mn==1)return p^1;
    	for(int i=1;i<=n;++i)a[i]>>=1;
    	int d=a[1];
    	for(int i=1;i<=n;++i)d=__gcd(d,a[i]);
    	for(int i=1;i<=n;++i)a[i]/=d;
    	calc(p^1);
    }
    int main()
    {
    	n=read();for(int i=1;i<=n;++i)a[i]=read();
    	puts(calc(1)?"First":"Second");
    	return 0;
    }
    

    E - Rearranging

    翻译

    给定一个数列,先手可以任意排列,后手每次可以交换相邻的两个互质的数,先手会让字典序最小,后手会让字典序最大,求最终排列。

    题解

    先考虑给定一个排列,后手如何让字典序最大。每个数向后面的所有和它不互质的数连边,求一遍拓扑序即可。那么我们现在来考虑如何让先手构造这个排列,首先我们把不互质的数之间连双向边,构成一个图,对于每一个联通块而言,我们显然要拉一条字典序最小的链出来,直接按顺序(dfs)一遍就好了。这样子给边定向跑拓扑排序即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define MAX 2020
    inline ll read()
    {
    	ll x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Line{int v,next;}e[MAX*MAX];
    int h[MAX],cnt=1,dg[MAX];
    vector<int> E[MAX];
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;dg[v]+=1;}
    inline void ADD(int u,int v){E[u].push_back(v);}
    int n;
    ll a[MAX];
    priority_queue<int> Q;
    bool vis[MAX];
    void dfs(int u)
    {
    	vis[u]=true;
    	for(int v:E[u])if(!vis[v])dfs(v),Add(u,v);
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	sort(&a[1],&a[n+1]);
    	for(int i=1;i<=n;++i)
    		for(int j=i+1;j<=n;++j)
    			if(__gcd(a[i],a[j])>1)ADD(i,j),ADD(j,i);
    	for(int i=1;i<=n;++i)if(!vis[i])dfs(i);
    	for(int i=1;i<=n;++i)if(!dg[i])Q.push(i);
    	while(!Q.empty())
    	{
    		int u=Q.top();Q.pop();printf("%lld ",a[u]);
    		for(int i=h[u];i;i=e[i].next)
    			if(!--dg[e[i].v])Q.push(e[i].v);
    	}
    	return 0;
    }
    

    F - Tree Game

    翻译

    见洛谷

    题解

    这场怕是博弈/构造疯了,我感觉后面几道题都长得一样的。

    判定方法是,如果一个子树必胜,那么必定存在一个它的儿子,满足儿子的权值小于当前点的权值,并且儿子是一个必败节点。这个很显然,因为如果这样一个儿子存在的话,你直接给他移过去,如果对面不服再移回来,你就再给他移过去,移到他服为止,当然了,他也只能服。否则的话不是必胜点,那么是一个必败点咯。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ll long long
    #define MAX 3030
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,a[MAX],sg[MAX];
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    void dfs(int u,int ff)
    {
    	sg[u]=0;
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=ff&&a[e[i].v]<a[u]){dfs(e[i].v,u);if(!sg[e[i].v])sg[u]=1;}
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
    	for(int u=1;u<=n;++u){dfs(u,0);if(sg[u])printf("%d ",u);}
    	puts("");return 0;		
    }
    
  • 相关阅读:
    css backgroud属性与雪碧技术
    css margin 外边距塌陷问题
    css 浮动元素与清除浮动
    css 盒模型的概念与使用
    七年iOS架构师教你如何一举拿下35K的Offer,(附面试技巧)
    iOS开发者月薪想要突破30K,需要经历+提升些什么?
    月薪 8K 与30K的程序员 区别到底在哪里?
    那些月薪35K以上的iOS开发者 都掌握了什么技能?
    从事 iOS 开发8年的面经——送给准备跳槽的你!
    想进BAT大厂的 iOS程序员,看完这个你还觉得Offer难拿吗???
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9710589.html
Copyright © 2011-2022 走看看