Codeforces Round #534 Div. 1

  A:用一列放竖着的方块,两列放横着的方块。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n;
char s[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	scanf("%s",s+1);n=strlen(s+1);
	int x=0,y=0;
	for (int i=1;i<=n;i++)
	if (s[i]=='0')
	{
		x++;
		if (x&1) cout<<1<<' '<<1<<endl;
		else cout<<3<<' '<<1<<endl;
	}
	else
	{
		y++;if (y>4) y=1;
		cout<<y<<' '<<2<<endl;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  B:先询问2k 2k+1,假设已经知道了a>2k,则当a>2k+1时,后者大,否则前者大。这样可以倍增出一个a的取值区间。注意到在区间内x mod a值开始单增,中间突变为0(即x=a),然后又单增,并且最开始的值要比最终的值大。于是拿2k+1和一个二分值比较即可。注意特判a=1的情况,询问0和1即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
char s[10];
signed main()
{
	cin>>(s+1);
	while (s[1]!='e')
	{
		cout<<'?'<<' '<<0<<' '<<1<<endl;
		char c;cin>>c;
		if (c=='x') cout<<'!'<<' '<<1<<endl;
		else
		{
			int x;
			for (int i=0;i<30;i++)
			{
				cout<<'?'<<' '<<(1<<i)<<' '<<(1<<i+1)<<endl;
				cin>>c;
				if (c=='x') {x=i;break;}
			}
			int y=(1<<x+1);
			int l=(1<<x)+1,r=y-1,ans=y;
			while (l<=r)
			{
				int mid=l+r>>1;
				cout<<'?'<<' '<<mid<<' '<<y<<endl;
				cin>>c;
				if (c=='x') l=mid+1;
				else ans=mid,r=mid-1;
			}
			cout<<'!'<<' '<<ans<<endl;
		}
		cin>>(s+1);
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  C:二选一当然是考虑问题间有什么关系。随便找一棵dfs树,如果深度>=n/k,那么显然有一条长度为n/k的简单路径;否则由抽屉原理,至少有一层的点数超过k,由此可得树的叶子数量超过k。注意到由于每个点度数至少为3,叶子至少会往上连两条边。我们考虑对每个叶子构造一个以其为标记的环。唯一的要求是环长不能为3的倍数,由于我们有至少两条边,所以可以得到至少三个包含该叶子的环,容易发现其中一定存在一个满足要求的。并且由于环长不会超过树的深度,所以总输出量也是O(n)的。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<cassert>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m,k,p[N],deep[N],fa[N],t,root=1;
bool flag[N],isleaf[N];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k) 
{
	flag[k]=1;int son=0;
	for (int i=p[k];i;i=edge[i].nxt)
	if (!flag[edge[i].to])
	{
		deep[edge[i].to]=deep[k]+1;
		fa[edge[i].to]=k;
		son++;
		dfs(edge[i].to);
	}
	if (son==0) isleaf[k]=1;
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
#endif
	n=read(),m=read(),k=read();
	for (int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		addedge(x,y),addedge(y,x);
	}
	deep[root]=1;dfs(root);
	for (int i=1;i<=n;i++)
	if (deep[i]>=n/k+(n%k>0))
	{
		cout<<"PATH"<<endl;cout<<deep[i]<<endl;
		for (int x=i;x!=root;x=fa[x]) printf("%d ",x);
		cout<<root;
		return 0;
	}
	cout<<"CYCLES"<<endl;
	for (int i=1;i<=n;i++)
	if (isleaf[i])
	{
		bool f=0;
		for (int j=p[i];j;j=edge[j].nxt)
		if (edge[j].to!=fa[i]&&(deep[i]-deep[edge[j].to])%3!=2) 
		{
			printf("%d\n",deep[i]-deep[edge[j].to]+1);
			for (int x=i;x!=edge[j].to;x=fa[x]) printf("%d ",x);
			printf("%d\n",edge[j].to);
			f=1;break;
		}
		if (!f)
		{
			int u=0,v=0;
			for (int j=p[i];j;j=edge[j].nxt)
			if (edge[j].to!=fa[i])
				if (!u) u=edge[j].to;else if (!v) v=edge[j].to;
				else break;
			if (deep[u]<deep[v]) swap(u,v);
			printf("%d\n",deep[u]-deep[v]+2);
			printf("%d ",i);
			while (u!=v) printf("%d ",u),u=fa[u];
			printf("%d\n",v);
		}
		k--;if (k==0) break;
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10409630.html