正题
题目大意
一个长度为nnn的序列aaa。
对于一个数每秒可以将一个二进制位取反或异或aaa中的一个数。
qqq个询问,询问从xxx变化到yyy最少要多少秒。
解题思路
对于一个x和yx和yx和y,设
xxorw=yx\ xor\ w=yx xor w=y
⇒x=yxorw\Rightarrow x=y\ xor\ w⇒x=y xor w
xxory=wx\ xor\ y=wx xor y=w
所以我们对于每个询问,我们只需要求000变成www的距离就好了。
由于起点只有一个,我们可以用bfsbfsbfs预处理000到www距离。
时间复杂度:O(220(n+20)+q)O(2^{20}(n+20)+q)O(220(n+20)+q)
codecodecode
#include<cstdio>
#include<queue>
#include<cctype>
#define MS 2097151
using namespace std;
int n,Q,a[25],v[MS+10];
queue<int> q;
inline char Getchar()
{static char buf[100000],*p1=buf+100000,*pend=buf+100000;if(p1==pend){p1=buf; pend=buf+fread(buf,1,100000,stdin);if (pend==p1) return -1;}return *p1++;
}
inline long long read()
{char c;int d=1;long long f=0;while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;return d*f;
}
inline void write(register long long x)
{if(x<0)write(45),x=-x;if(x>9)write(x/10);putchar(x%10+48);return;
}
void bfs()//预处理
{v[0]=1;q.push(0);int y,i;while(!q.empty()){int x=q.front();q.pop();for(i=1;i<=n;i++)//异或a中的数{y=x^a[i];if(!v[y]){v[y]=v[x]+1;q.push(y);}}for(i=0;i<=20;i++)//位数取反{y=x^(1<<i);if(!v[y]){v[y]=v[x]+1;q.push(y);}}}
}
int main()
{freopen("data.in","r",stdin);freopen("data.out","w",stdout);n=read();Q=read();for(int i=1;i<=n;i++)a[i]=read();bfs();for(int i=1;i<=Q;i++) {int x,y,z;x=read();y=read();write(v[x^y]-1);putchar('\n');}
}