Codeforces 1325 D. Ehab the Xorcist (异或)

题目链接

题目大意

给出一个 u 和一个 v ,要求构造出最短的一个数组,使得所有元素异或的结果为 u,所有元素之和的结果为 v。

注意输入为 long long

题目思路

看到此题我一点思路都没有

最近写题目感觉有一个规律,如果数据开到long long那么基本都是分类讨论

因为元素范围多,所以时间复杂度,我觉得基本都是o(1)o(log(n))的复杂度我还没见过

正题

首先先了解一个知识点:异或可以考虑为不进位的加法

我认为此题最关键的就是要明白数组元素最多3个。

如果可以划分。显然可以分为 (v-u)/2,(v-u)/2,u。显然可以得出这三个元素满足题目条件。

然后分类即可

1:当 u 和 v 都为 0 时,答案为 0

2:当 u=v时,答案为 u 或者 v

3:由于异或是不进位的加法,所以u一定要小于等于v,所以当 u>v 时,答案为 −1

4:两个相同的数异或值肯定为 0 , 0 异或任何数又是那个数的本身,所以我们设 a=(v−u)/2 然后输出 a,a,u肯定符合。

5:如果 (v−u)%2!=0 那么肯定是 −1。

6:还有一种长度为 2 的情况,若有(a^u)=(a+u),则可将前两项进行合并,这个点最难。输出。

注意:和 ^ 这个符号有关最好打个括号,他的优先级比较玄学,其实就是比较低

代码

#include<cstdio>
using namespace std;
typedef long long ll;
ll u,v,n;
int main(){
    scanf("%lld %lld",&u,&v);
    if(u>v||(v-u)%2==1){
        n=-1;
    }else if(u==0&&v==0){
        n=0;
    }else if(u==v){
        n=1;
    }else if((u^((v-u)/2))==(v+u)/2){//判断是否可以合并,注意其优先级
        n=2;
    }else{//分为(v-u)/2,(v-u)/2,(v+u)/2
        n=3;
    }
    printf("%lld\n",n);
    if(n==1){
        printf("%lld\n",u);
    }else if(n==2){
        printf("%lld %lld\n",(v-u)/2,(u+v)/2);
    }else if(n==3){
        printf("%lld %lld %lld\n",(v-u)/2,(v-u)/2,u);
    }
    return 0;
}

发布了68 篇原创文章 · 获赞 2 · 访问量 2262

猜你喜欢

转载自blog.csdn.net/m0_46209312/article/details/104975364
今日推荐