大致题意
给你一个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;
}