2019 ICPC 徐州区域赛 - A Cat(异或性质)

题目链接


题目大意

[ 1 , 1 0 18 [1,10^{18} [1,1018个物品每个物品的价值为 i i i,给出一个区间 [ L , R ] [L,R] [L,R]的物品,只能买连续的东西其总价值为这几个连续的物品价值异或结果,问 S S S最多能买多少物品。

解题思路

关于本题最重要的结论是:每个偶数和与它相邻且大于它的那个奇数异或之后结果一定为1。此外还需要知道异或运算具有交换律和结合律,任何数和它本身异或之后为 0 0 0,任何数和 0 0 0异或值不变。

然后这道题就差不多是模拟了,当区间长度超过 4 4 4之后一定能把 4 k 4k 4k的数异或成 0 0 0。然后就是分情况考虑,区间长度小于 4 4 4直接暴力,大于四了,按左区间和右区间奇偶性分四个情况讨论。(写的代码略啰嗦)需要注意的地方是位运算的优先性比四则运算甚至比较运算符都低,防止错误的话在每次位运算时加上括号。

代码:

#include <iostream>

using namespace std;
typedef long long ll;
ll solve(ll l,ll r,ll s){
    ll p=r-l+1;
    if(p<5){
        if(p==1){
            if(l<=s) return 1;
            else return 0;
        }else if(p==2){
            if( (l^r)<=s) return 2;
            else if(l<=s) return 1;
            else return 0;
        }else if(p==3){
            ll t=l^(l+1)^r;
            if(t<=s) return 3;
            else if( (l^(l+1))<=s || (r^(l+1))<=s) return 2;
            else if(l<=s) return 1;
            else return 0;
        }else if(p==4){
            ll t=l^(l+1)^(l+2)^r;
            if(t<=s) return 4;
            else if( (t^r)<=s || (t^l)<=s) return 3;
            else if( (l^(l+1))<=s || ((l+1)^(l+2))<=s || ((l+2)^r)<=s) return 2;
            else if(l<=s) return 1;
            else return 0;
        }
    }else{
        ll d=p/4;
        if( (l&1) && !(r&1)){
            if(p%4){
                ll q=4*d;
                if( (l^r)<=s) return q+2;
                else if(l<=s) return q+1;
                else return q;
            }else{
                d--; ///这个有可能会漏
                ll q=4*d;
                if( (l^1^r)<=s) return q+4;
                else if( (l^1)<=s || (1^r)<=s) return q+3;
                else if(1<=s) return q+2;
                else if(l<=s) return q+1;
                else return q;
            }
        }else if( (l&1) && (r&1) ){
            ll t=p%4;
            ll q=4*d;
            if(t==1){
                if(l<=s) return q+1;
                else return q;
            }else if(t==3){
                if((l^1)<=s) return q+3;
                if(1<=s) return q+2;
                else if(l<=s) return q+1;
                else return q;
            }
        }else if( !(l&1) && (r&1) ){
            ll t=p%4;
            ll q=4*d;
            if(t){
                if(1<=s) return q+2;
                else return q;
            }else{
                return q;
            }
        }else if( !(l&1) && !(r&1) ){
            ll t=p%4;
            ll q=4*d;
            if(t==1){
                if(r<=s) return q+1;
                else return q;
            }else if(t==3){
                if((1^r)<=s) return q+3;
                else if(1<=s) return q+2;
                else return q;
            }
        }
    }
}
int main(){
    ll T,l,r,s;
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&l,&r,&s);
        ll ans=solve(l,r,s);
        if(!ans) printf("-1\n");
        else printf("%lld\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值