如题:
求[a,b]内所有数的异或值,f[i]=i.
为了方便用f([a,b])表示[a,b]内所有数的异或值.
首先,根据异或的规则可得
f([a,b])=f([1,b])^f([1,a-1]).
所以只要会求f([1,n])就可以了
1.
若a是偶数,则a^a+1=1;
这样就可以掐头去尾 中间的数两两配对 就算出来了
代码:
ll GEt_ans(ll a)//求f([1,a])
{
if(a==0)
return 0;
if(a%2==1){
if(((a-1)/2)%2==1)//掐头
return 0;
else
return 1;
}
else{
if(((a-2)/2)%2==1)//掐头去尾
return a;
else
return 1^a;
}
}
上面的算法也可以直接算f([a,b]),小改一下就行了.
不过通过上边的算法可以发现一个规律
任意一个数一定是上面四种情况之一 打个表可以发现 恰好是4个一循环
然后就有了第二种方法
2
ll GEt_ans(ll a)
{
if(a%4==1)
return 1;
else if(a%4==2)
return a+1;
else if(a%4==3||a==0)
return 0;
else
return a;
}
上边是我写完看的别人的思路,orz.
下边是我自己xjb推推出来的,比上边慢了好多,orz
3
思路是把1到x的所有数化成二进制(这一步不需要代码实现,只是想的时候把数看城二进制),然后从低到高逐位计算.
算了,看上边两个就行了,这个我就写下来自己看看,orz
ll GEt_ans(ll x,ll y,ll sum)//求的是f([1,x]),
{
if(y>x)
return sum;
ll num=0;
ll n=x-y+1;
ll res=n%(y*2);
if(res!=0){
if(res>=y)
num+=y;
else
num+=res;
}
n-=res;
num+=n/2;
if(num%2==1)
sum+=y;
y*=2;
GEt_ans(x,y,sum);
}