Codeforces Round #628 (Div. 2)

Codeforces Round #628 (Div. 2)

http://codeforces.com/contest/1325

A - EhAb AnD gCd

#include<bits/stdc++.h>
using namespace std;
int t,x;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&x);
		printf("1 %d\n",x-1);
	}
	return 0;
}

B - CopyCopyCopyCopyCopy

思路:因为要严格递增,事实上每个最多取到一次,然后原数组复制了n遍,即在每一遍中取一个数即可,等于说可以将原数组中的数按任意顺序取出,那么排好序后严格递增的子序列就是最优

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,a[MAXN],t;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i = 1;i <= n;++i)
			scanf("%d",&a[i]);
		sort(a+1,a+n+1);
		int cnt = 1;
		for(int i = 2;i <= n;++i)
			if(a[i] > a[i-1])
				++cnt;
		printf("%d\n",cnt);
	}
	return 0;
}

C - Ehab and Path-etic MEXs

思路:因为最长那段肯定要有0,1,2,…这样连续的数字,如果要放0,1,0,1必然会出现在一条路径上,直接找到连有至少三条边的节点将0,1,2分别分配给3边即可让他们三不会出现在同一条路径

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,head[MAXN],tot;
inline void init()
{
	tot = 0;
	memset(head,-1,sizeof(int)*(n+1));
}
struct edge
{
	int u,v,x;
}edg[MAXN];
int du[MAXN];
vector<int> ve[MAXN];
int main()
{
	scanf("%d",&n);
	int u,v;
	for(int i = 1;i < n;++i)
	{
		scanf("%d%d",&u,&v);
		edg[i].u = u,edg[i].v = v;
		++du[u],++du[v];
		ve[u].push_back(i),ve[v].push_back(i);
		edg[i].x = -1;
	}
	int cnt = 0;
	for(int i = 1;i <= n;++i)
	{
		if(du[i] >= 3)
		{
			for(int j = 0;j < ve[i].size();++j)
			{
				edg[ve[i][j]].x = cnt;
				++cnt;
			}
			break;
		}
	}
	for(int i = 1;i < n;++i)
		if(edg[i].x == -1)
		{
			edg[i].x = cnt;
			++cnt;
		}
	for(int i = 1;i < n;++i)
		printf("%d\n",edg[i].x);
	return 0;
}

D - Ehab the Xorcist

思路:首先设a[1]为u,a[2],a[3]为0,很明显要在不改变异或值的情况下只能让两个数字同时异或上一个数,而0,1同时异或上一个数和不变,故异或后和必然增大,u <= v
如果v-u为奇数,那么末位会有个1需要加上,但末位必须有两个数字都异或上1总的异或值才不会改变,故v-u必须为偶数
将v-u分为两份,设tmp = (v-u)/2,即tmp中1的位需要有两个数字异或上
现假设要异或上一个1,当a[1]中对应位为0时,直接将这一位变为1然后a[2]的这一位也变为1即可
但如果a[1]中对应位为1,让a[1]去异或上它sum不会增大,故让a[2],a[3]异或上它
最终可以发现a[1] = u|tmp,a[2] = tmp,a[3] = u&tmp
再把0剔除掉即可

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll u,v,a[5];
int main()
{
	scanf("%lld%lld",&u,&v);
	if(u > v || ((v-u)&1))
		printf("-1\n");
	else if(u == v)
	{
		if(u == 0)
			printf("0\n");
		else 
			printf("1\n%lld\n",u);
	}
	else
	{
		a[2] = a[3] = 0;
		ll tmp = (v-u)/2;
		a[1] = u | tmp;
		a[3] = u & tmp;
		a[2] = tmp;
		int n = 0;
		for(int i = 1;i <= 3;++i)
			if(a[i])
				++n;
		printf("%d\n",n);
		for(int i = 1;i <= n;++i)
			printf("%lld ",a[i]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值