首页 > 其他 > 详细

区间或和-位运算

时间:2019-02-07 16:47:28      阅读:225      评论:0      收藏:0      [点我收藏+]

链接:https://ac.nowcoder.com/acm/contest/332/G
来源:牛客网

题目描述

求a|(a+1)|(a+2)|...|(b-1)|b。

其中|表示[按位或](https://baike.baidu.com/item/%E6%8C%89%E4%BD%8D%E6%88%96)。

输入描述:

多组输入,每行两个数表示a和b

输出描述:

对于每组输入,输出一个数a|(a+1)|(a+2)|...|(b-1)|b。
示例1

输入

99 109
68 77
55 66
34 43
1111234 1114321

输出

111
79
127
47
1179647

备注:

输入不超过10000行,0a,b10180≤a,b≤1018,ab

思路分析:
1.位运算,肯定是用二进制做题啦
2.a<=b,二进制从左往右数,肯定有某个位,有b为1,a为0,连续或运算,会把后面的位都用1填满就是结果了
比如
a=1100001110
b=1101010110
c=1101111111
从左往右数第四位开始用1补满

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<vector>
#include<iostream>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
#define ll long long
ll two[65];
string s1,s2;
void init()//打印2的次方表
{
    two[0]=1;
    for(int i=1;i<=62;i++)
        two[i]=two[i-1]*2;
}
string trans(ll x)//把数字转化为二进制的字符串
{
    string res="";
    ll r;
    while(x)
    {
        r=x%2;
        res=char(r+0) + res;
        x=x/2;
    }
    return res;
}

void addzero()//字符串长度不同则前面补0
{
    int len1=s1.size();
    int len2=s2.size();
    for(int i=1;i<=len2-len1;i++)
        s1=0+s1;
}

int num()//出现第一个不同的数位从右往左第几位
{
    int len=s1.size();
    for(int i=0;i<len;i++)
    {
        if(s1[i]!=s2[i])
            return (len-i);
    }
    return 0;
}

ll add(int x)//累计多出的那一段
{
    ll res=0;
    for(int i=0;i<x;i++)
        res+=two[i];
    return res;
}

int main()
{
    ll a,b;
    init();
    while(scanf("%lld%lld",&a,&b)!=EOF)
    {
        s1=trans(a);
        s2=trans(b);
        addzero();
        ll more = add( num() );
        ll ans = b|more;
        printf("%lld\n",ans);
    }
    return 0;
}

 



区间或和-位运算

原文:https://www.cnblogs.com/shoulinniao/p/10354907.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!