cf 1325

D题
题目链接

题目大意:
给出一个 u 和一个 v ,要求构造出最短的一个数组,使得
所有元素异或的结果为 u
所有元素之和的结果为 v
找不到输出-1 否则输出数组元素的个数 再输出数组内的元素

解题思路:
需要进行几个特判
(1)首先 在二进制中 只有一个数的时候 异或=相加和 (即自己等于自己) 所以如果u等于v并且都大于0时 我们输出u就好了
因为相同的数字异或值为0 题目又是要求最短的数组
所以我们大可直接 出来三个数字 u k k
k k异或就为0了 一个数跟0异或是自己本身 所以0^u还是u
然后我们再让 u+k+k=v 解得k= (v-u)/2
这时(2)特判条件就出来了,如果u=0,v=0,或者(v-u)不能整除2 直接输出-1
题目中要求数组最短,所以我们要考虑两个元素可不可以满足
即把 u+k看成一个数 所以 u^ k^k =(u+k) ^ k 约分后发现 u ^ k =u+k
那么什么情况下才能满足呢?
即 u和k 的二进制上的1不会在同一位同时出现时 这时的异或运算就等于二进制的加法运算
即 (u&k)==0时 ,与运算是同时为1 为1 ,否则为0
所以这就是我们的(3)特判条件

#include<iostream>
using namespace std;
long long u,v,w;
int main()
{
    
    
	cin>>u>>v;
	if(u==0&&v==0)//空数组 
	   cout<<"0"<<endl;
	else if(u==v)
	{
    
    
	   cout<<"1"<<endl;
	   cout<<u<<endl;//本身 
    }
	else if(u>v||(v-u)%2)
	   cout<<"-1"<<endl;//无解 
	else
	{
    
    
		w=(v-u)/2;
		if((u&w)==0)
		{
    
    
			cout<<2<<endl;
			cout<<w<<" "<<w+u<<endl; 
		}
		else
		{
    
    
			cout<<3<<endl;
			cout<<u<<" "<<w<<" "<<w<<endl;
		}
	}
	return 0;
}

C题
题目链接
题目大意:给定一棵具有 n 个点的树,对树边标号为 0,1,2,…,n−2 。定义 MEX(u,v) :点 u 到 v 的路径上最小的未出现的标号;现请你给出一种构造方案使得对于所有 MEX(u,v) 的最大值最小

解题思路:
只要有一个点度数大于2,那么将其中的三个出边分别连0、1、2就可以了,剩下的随便连。
因为这样的话,mex一定是不大于2的,不可能有一个路径同时经过标记为0、1、2的这三条边。

#include <bits/stdc++.h>
const int maxn=1e5+10;
using namespace std;
int a[maxn],d[maxn],u[maxn],v[maxn];
int main()
{
    
    
    int n,x;
    int i,j;
    cin>>n;
    for(i=1;i<n;i++)
    {
    
    
    	cin>>u[i]>>v[i];
    	a[i]=-1;
    	d[u[i]]++;
    	d[v[i]]++;
	}
	x=-1;
	for(i=1;i<=n;i++)
	{
    
    
		if(d[i]>2)
		{
    
    
			for(j=1;j<n;j++)
			{
    
    
				if(u[j]==i||v[j]==i)
				{
    
    
					a[j]=++x;
					if(x==2)
					  break;
				}
			}
			break;
		}
	}
	for(i=1;i<n;i++)
	  if(a[i]==-1)
	     a[i]=++x;
	for(i=1;i<n;i++)
	  cout<<a[i]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43819762/article/details/104889012