求连续自然数区间的异或值

4 篇文章 0 订阅
3 篇文章 0 订阅

如题:
求[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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值