Codeforces 862C(构造)

来源:互联网 发布:知乎三国第一人 编辑:程序博客网 时间:2024/05/01 12:50

最近好像老是跟构造过不去눈_눈
题意:给出n与x,要求先说可不可以给出n个数字使其异或和为x,如果可以,那么输出这n个数字。
思路: 1、首先要知道(x^y^(x+y))=0,手动列一下式子就粗来了눈_눈
2、然后0和k(k为任何数字)异或的结果是k(当年pascal的基础大概是被我吃了)
一开始定义的max1和max2的位数极长,换算成十进制超过六位,为的是防止输出重复;而从1输出到n-3纯粹是凑位数,事实上只要三位就可以了。
当1到n-3的异或和为x时,凑一个零。
当1到n-3的异或和不为x时,想办法把它凑成x,那么这时候就需要活用第二条思路了:0^k=k——->x^(y^z)^y^z=x
注意:max1和max2必须为2的幂次方,因为这样的话在2进制下后面跟着一串的零,使其与比其小的数异或时能保证稳定的增大,避免与1~n-3有重复。
Gloria的补充:

考虑到异或的性质那么肯定要有两个相同的,怎么让我们能让他们不同呢?其实想明白了其实很简单,1e5大约是17为,1e6为20位.
这里我们为了让他们不同构造两个数 (1<<17) 和(1<<18) 这样和他们异或的和一定不同,因为17 18 位都是0
肯定不一样了,剩下的n-2个数,有n-3个我们让他们从1-n-3输出,最后一个数构造为 x
^(1…n-3)^(1<<17)^(1<<18)。这样就很简单的保证了n个数互不相同。

大晚上的,看题解。没看懂最开始为啥要从1输出到n-3,于是乎半夜三点骚扰大狗……我果然还是太菜了QWQ

#include<bits/stdc++.h>using namespace std;const int max1=1<<17;const int max2=1<<18;int main(){    int n,x,tot=0;    while(~scanf("%d%d",&n,&x)){        if(n==2 && x==0){            printf("NO\n");            break;        }        if(n==1){            printf("YES\n%d\n",x);            break;        }        if(n==2){            printf("YES\n0 %d\n",x);            break;         }        printf("YES\n");        for(int i=1;i<=n-3;i++){            printf("%d ",i);            tot^=i;        }        if(tot==x){            cout<<max1+max2<<" "<<max1<<" "<<max2<<endl;        }        else cout<<"0 "<<max1<<" "<<((max1^tot)^x)<<endl;    }    return 0;}

结论:对异或运算还不够熟悉,题目做得太少……
掌握好基本公式很重要啊

原创粉丝点击