Codeforces Round #676 (Div. 2) 题解

154 阅读1分钟

A

思路

假设a<ba<b,且aamm位,bbnn位。那么xx的位数必定小于等于mmxx中超过mm位的数字不可能令答案变得更小,因为超过mm位要想让答案更小,只能异或掉bb的一个11,那么xx的该位必然是11,这样就会让aa在此增加一个11,答案并没有变化。
考虑不超过mm位的部分。要想让答案变小,就要让a,ba,b11减少,因此只能对a,ba,b均为11的一位进行异或,否则不会优化答案。
通过上述分析,易得x=a&bx=a\&b

证明:(a(a&b))+(b(a&b))=ab(a\oplus(a\&b))+(b\oplus(a\&b))=a\oplus b
自己不太严谨的证明:设o=a&bo=a\&b。则oo是由a,ba,b共有的11组成的数字。aoa\oplus oaa独有的11组成数字。bob\oplus o同理。二者相加即a,ba,b二者各自独有的11组成的数字,与aba\oplus b效果相同。

代码

考场代码与思路略有差异。

#include <iostream>
using namespace std;
int t,a,b;
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>a>>b;
		if(a>b)
			swap(a,b);
		int x=0;
		int cur=1;
		while(cur<=a)
		{
			if(a&cur && b&cur)
			{
				x|=cur;
			}
			cur<<=1;
		}
		cout<<(a^x)+(b^x)<<endl;
	}
}

B

思路

途中不能改变遍历规则,且在大图中很难堵,不如从起点和终点堵截。
从起点出发只能向右或向下,要到达终点也只有这两个方向。只需让起点旁边的两个格同号且均与终点旁边的两个格异号即可。 不论这四个格初始状态是什么,都可以在两步之内实现最终状态。

代码

if太多太恶心懒得写了

C

思路

非常巧妙的一个题,把倒数第二个反转到最后面,再把中间所有的(不包含开头和结尾)反转到最前面,这样就只有最后一个字符不满足回文条件了,但是此时正数第二个正是最后那个字符,把第二个反转到前面即可。

#include<iostream>
using namespace std;
int n;
int main()
{
	string str;
	cin>>str;
	n=str.size();
	printf("3\nR %d\nL %d\nL 2\n",n-1,n);
}

D

思路

找出横纵坐标之差再根据路径权值求和即可

代码