区间或和-(位运算)
链接: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行,0≤a,b≤10180≤a,b≤1018,a≤b
思路分析:
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; }