HDU 5661/BC 79B Claris and XOR

20 篇文章 0 订阅

开始时想按照数位dp来做 先考虑x 有a≤x≤b 从高位到低位考虑 举个例子 

a为11101110100

b位11100101010

若开始的几位相同 则x的取值固定 前4位一定是1110 从第五位开始有两种选法 设x的第五位为1  第六位为0 那么剩下的位就没有限制 (因为x一定满足a≤x≤b了) 

我们称没有限制为自由态,当x到达自由态后 无论y的当前位是0还是1 x只要选与之相符的1或0就可以了 也就是说最后的结果剩下的位均为1

而x到达自由态之前 一定都是前缀为a或者b的  所以我们可以枚举 假设x沿着a或b y沿着c或d(枚举4次) 

从高位开始枚举 如果可以进入自由态并且等同于本来的值或者更优 剩下的位均赋1即可

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#define mem(x,y) memset(x,y,sizeof(x))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
#define bug puts("===========");
const double pi=(acos(-1.0));
const double eps=1e-8;
const ll INF=1e18+10;
const ll inf=1e14;
const int maxn=1000+10;
const int mod=100000007;
/*===============================*/
vector<int>a,b,c,d;
vector<int> go(ll x){
    vector<int>vec;
    while(x){
        vec.pb(x&1);
        x>>=1;
    }
    return vec;
}
int n,stab,stcd;
ull fuck(vector<int>a,vector<int>b){
    ull z=0;
    int ha=0,hb=0;
    for(int i=n-1;i>=0;i--){
        ull ans=0;
        if(i<stab&&a[stab]==a[i]&&b[i]==a[i]) ha=1;
        if(i<stcd&&b[stcd]==b[i]&&a[i]==b[i]) hb=1;
        if(ha||hb) ans=1;
        else ans=a[i]^b[i];
        z=z*2+ans;
    }
    return z;
}
int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--){
        ll aa,bb,cc,dd;
        scanf("%I64d%I64d%I64d%I64d",&aa,&bb,&cc,&dd);
        a=go(aa); b=go(bb); c=go(cc); d=go(dd);
         n=max(max(a.size(),b.size()),max(c.size(),d.size()));
        while(a.size()<n) a.pb(0); while(b.size()<n) b.pb(0);
        while(c.size()<n) c.pb(0); while(d.size()<n) d.pb(0);
        stab=-1,stcd=-1;
        for(int i=n-1;i>=0;i--){
            if(stab==-1&&a[i]!=b[i]) stab=i;
            if(stcd==-1&&c[i]!=d[i]) stcd=i;
        }
        ull z=max(max(fuck(a,c),fuck(a,d)),max(fuck(b,c),fuck(b,d)));
        printf("%I64u\n",z);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值