大致题意
给你一个n,m
要你构造出一个有n个数的方案使得这n个数的异或和为m
要是不可以就输出0
这个n个数不能大于10^6
n,m都在10^5
题解
刘智嘎的做法
先“随便确定n个数” ,然后再进行选学的调整。。
但这个做法很有问题。。
你要是真的“随便”确定的话,会WA掉。。
对确定数的要求比较高。。十分玄学
#include<cstdio>
#include<cstring>
const int N=1000005;
bool bo[N];
int a[N];//最后的东西
int n,m;
int main()
{
memset(bo,false,sizeof(bo));
scanf("%d%d",&n,&m);
for (int u=1;u<=n;u++)
{
a[u]=(1<<18)-u+1;
bo[a[u]]=true;
m=m^a[u];
}
for (int u=1;u<=n;u++)
{
if (m==0) break;
if (bo[m^a[u]]==false)
{
a[u]=a[u]^m;
m=0;
break;
}
else
{
int t=m|a[u];
int last=m;
if (bo[t]==false)
{
bo[a[u]]=false;
m=m^a[u];
a[u]=a[u]|last;
bo[t]=true;
m=m^a[u];
}
}
}
if (m!=0) printf("NO\n");
else
{
printf("YES\n");
for (int u=1;u<=n;u++)
{
printf("%d ",a[u]);
}
}
return 0;
}
标解
还是标解的构造靠谱。。
我们这次真的可以随便地构造n-3个数,只要不重复就行。。当然,这n-3个数不要超过n
然后我们设PW=1<<17
我们看一下这个n-3个数的异或和y
要是刚好和m相等,那么我们就把剩下的数弄到0就好了
PW*2,PW,PW+PW*2就是可行的方案
要是不相等
那么我们就弄PW,0,PW^m^y就好了
但感觉这种题还是很妙啊。。
你会了一题不一定可以会第二题。。比如说你把n开到10^6我可能就不会了。。
#include<cstdio>
#include<cstring>
const int PW=1<<17;
int n,x;
int main()
{
scanf("%d%d",&n,&x);
if (n==2&&x==0)
{
printf("No\n");
return 0;
}
printf("YES\n");
if (n==1) printf("%d\n",x);
else if (n==2) printf("%d %d\n",0,x);
else
{
int y=0;
for (int u=1;u<=n-3;u++)
{
printf("%d ",u);
y^=u;
}
if (x==y) printf("%d %d %d\n",PW,PW*2,PW*2+PW);
else printf("%d %d %d\n",0,PW,PW^x^y);
}
return 0;
}