SCUT - 223 - Maya - 构造
给定两个数N,M,构造M个在[0,80000]以内的互不相同的数使之异或和为N。
首先特判一下M<=2的两个简单情况,还有坑爹的-1!
然后想办法构造。
好像从哪里得到的启发只要把最后一次调整交给最后的数字就可以了。
但是这次调整可能会和前面生成的数字重复,这怎么搞呢?
先命令前面从1开始连续生成M-2个数字。
然后现在的异或和绝对是在10000以内的某个数,或许是0。是0那就麻烦了,就要避免,避免的方法就是最后一次生成的时候多搞一个1。那么现在cur不为0了。最多也是生成到10000多个零头。
然后生成一个(1<<14)|cur,前面就多了一个1,后面全部被搞成0,这个数字这么大肯定也没出现过。
最后异或上N就可以回答了?前面多了一个1唯一能重复的就是和倒数第二个数(1<<14)|cur重复,这种情况就是N为0的时候导致最后要异或一个一样的来取消。
所以在进行这些之前先判断N是不是0?假如是的话,倒数第二个就生成(1<<14),这下异或了之后就是前面一个1,后面跟一串非0的数字cur,最后把他们一起取消掉,肯定也比(1<<14)要大。所以是合法的。
此方法构造需要在[0,32768]以内。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
ll x = 0;
//int f = 0;
char c;
do {
c = getchar();
/*if(c == '-')
f = 1;*/
} while(c < '0' || c > '9');
do {
x = (x << 3) + (x << 1) + c - '0';
c = getchar();
} while(c >= '0' && c <= '9');
//return f ? -x : x;
return x;
}
inline void _write(int x) {
if(x > 9)
_write(x / 10);
putchar(x % 10 + '0');
}
inline void write(int x) {
if(x < 0) {
putchar('-');
x = -x;
}
_write(x);
putchar('\n');
}
void TestCase(int ti);
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out","w",stdout);
#endif // Yinku
int T = 1;
for(int ti = 1; ti <= T; ti++)
TestCase(ti);
}
/*--- ---*/
void TestCase(int ti) {
int N,M;
while(~scanf("%d%d",&N,&M)){
if(M==1){
printf("%d\n",N);
}
else if(M==2){
if(N==0){
puts("-1");
}
else{
printf("0 %d\n",N);
}
}
else{
int cur=0;
int id=0;
for(int i=1;i<=M-3;i++){
printf("%d ",id);
cur^=id;
id++;
}
while((cur^id)==0)
id++;
printf("%d ",id);
cur^=id;
if(N==0){
printf("%d ",(1<<14));
cur^=(1<<14);
printf("%d\n",cur^N);
}
else{
printf("%d ",(1<<14)|cur);
cur^=(1<<14)|cur;
printf("%d\n",cur^N);
}
}
}
}