Codeforces-#628-div2

CF#628-div2

  • AB
  • C-Ehab and Path-etic MEXs
  • D-Ehab the Xorcist

自己搞了次模拟,写了两个题就结束了。害。菜是原罪。。太菜了。写了10几分钟就结束了。C题 题目都没整明白。后面一个多小时完全不知道在做什么了。

题目链接:Codeforces-#628-div2

AB

A题:一个是1,一个是 sum-1即可。1 + sum-1 = sum。
B题 用set计数即可,循环下去,一定可以取到所有不重复的数。

C-Ehab and Path-etic MEXs

        题意硬是没读懂,,再次读题:n个点,n-1条边,每个边上有权值(0 ~ n-2),保证是树,求使得树上所有对所在的简单路径的 最大MEX值 最小的 一组权值。MEX指的是没有出现在简单路径里的最小非负正数。
        叶子结点使用的频率低–先安排权值,非叶结点使用频率高,要使得u-v的简单路径间未出现的值最小,就从大的值安排。
        贪心思路:是叶结点就从0往后递增,非节结点就从n-2往前递减。

#include
using namespace std;
const int M = 1e5+10;
int a[M], b[M];
int degree[M];

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i < n; ++i)
	{
		scanf("%d %d",a+i, b+i);
		degree[a[i]]++;
		degree[b[i]]++;
	}

	int nxt = 0, pre = n-2;
	for (int i = 1; i < n; ++i)
	{
		if (degree[a[i]] == 1 || degree[b[i]] ==  1)
			printf("%d\n", nxt++);// 叶子结点
		else printf("%d\n", pre--);//非叶结点
	}
	return 0;
} 

借鉴自 箱@子

D-Ehab the Xorcist

题意是求最短的序列a,使得满足a中所有元素异或后得到u,a中所有元素和为v,求序列a。
思路:
1 . u > v 时,无解,因为u > v 即u的最高位1 比 v的最高位1高,异或的元素中肯定在这一位上有一位1,所以和一定大于v,不会是v。
2 . u = v时,输出u即可。
3 . u < v时,普通的:三个数即可构造出,x = (v-u)/2-- u x x。但若(v-u)是奇数,(v-u)无法平分两份,输出-1。
考虑特殊情况(两个数):a^b = u, a + b = v; 异或就是不进位加法,这是关键,所以:a+b = a^b + 2(a&b),化简一下得到什么呢?a&b = (v-u)/2,设x = (v-u)/2=a&b,若x的二进制位为1,则a,b该位都为1,u的该位就为0;x的二进制位上为0时(a-b-u):0-1-1, 1-0-1, 0-0-0, u的该位,则不限制。
所以:当x的二进制位上为1(0)时,u上为0(不用考虑-x上已经为0),即x&u=0;不成立的情况就是x&u!=0,就需要输入一般情况。成立的时候–x&u = 0,即:x^u = x+u,就构造出:u+x, x 这个序列。
(证明一下 a+b = a^b + 2(a&b):a^b 把二进制a,b上不同的数都加上了–即0-1和1-0都加上了;对于1-1就靠a&b来处理了,a,b该位都为1, a&b的该位才为1,因为a,b该位都是1,所以乘2)。
思路参考自 Ehab the Xorcist

#include  
using namespace std;
const int M = 1e6;
typedef long long ll;

int main()
{
	ll u, v, x;
	scanf("%lld %lld", &u, &v) ;
	if (u == 0 && v == 0) puts("0");
	else if (u > v) 	puts("-1");
	else if (u == v)	printf("1\n%lld\n", u);
	else {
		x = (v - u) / 2;
		if ((v-u) & 1) puts("-1");
		else if ((x&u) == 0)
			printf("2\n%lld %lld\n", x, u+x);
		else printf("3\n%lld %lld %lld\n", u, x, x);
	}
	return 0;
}

你可能感兴趣的:(CF练习)