题目大意:
题目链接:https://jzoj.net/senior/#main/show/100047
题目图片:
http://wx1.sinaimg.cn/mw690/0060lm7Tly1fy7gss4ijmj30j50cujrv.jpg
http://wx4.sinaimg.cn/mw690/0060lm7Tly1fy7gss4gyaj30j20asdfx.jpg
已知数组,两种操作:
- 将变成
- 将二进制下任意一位取反。
求从变成的最少步数。
思路:
如果我们有一个数使得,那么很明显的就是我们要求的答案。
反过来得。
所以,其实到的最少步数就是到的最少步数!
那么就从开始,求出不超过的答案(因为最大就是了)。然后就可以输出了。
思维好题。
代码:
#include <cstdio>
#include <queue>
#define ri register
using namespace std;
const int N=1200000;
int n,u,v,Q,a[N],s,t,ans[N];
bool vis[N];
char c;
int read()
{
u=0;
c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
u=(u<<3)+(u<<1)+c-48,c=getchar();
return u;
}
int write(int x)
{
if (x>9) write(x/10);
putchar(x%10+48);
}
void bfs()
{
queue<int> q;
q.push(0);
vis[0]=1;
while (q.size())
{
u=q.front();
q.pop();
for (ri int i=1;i<=n;i++) //选择每一个数xor
if (!vis[u^a[i]])
{
vis[u^a[i]]=1;
ans[u^a[i]]=ans[u]+1;
q.push(u^a[i]);
}
for (ri int i=0;i<=19;i++) //选择每一位取反
{
if ((u&(1<<i))==(1<<i)) v=u-(1<<i);
else v=u+(1<<i);
if (!vis[v])
{
vis[v]=1;
ans[v]=ans[u]+1;
q.push(v);
}
}
}
}
int main()
{
n=read();
Q=read();
for (ri int i=1;i<=n;i++)
a[i]=read();
bfs();
while (Q--)
{
s=read();
t=read();
write(ans[s^t]);
putchar(10);
}
return 0;
}