[CSP-S模拟测试]:最大或(数学)

题目传送门(内部题141)


输入格式

  输入文件包含多组测试数据,第一行为一个正整数$T$,表示数据组数。
  接下来$T$行,每行两个正整数$l,r$。数据保证$l\leqslant r$成立。


输出格式

  输出$T$行,每行一个正整数,为满足条件的$x,y$进行或运算后的最大值,即输出$\max(x\ or\ y)$。


样例

样例输入:

3
1 10
1023 1024
233 322

样例输出:

15
1023
511


数据范围与提示

  对于$40\%$的数据,满足$r\leqslant 500$。
  对于$70\%$的数据,满足$r\leqslant 10^6$。
  对于$100\%$的数据,满足$1\leqslant l\leqslant r\leqslant 10^{18},1\leqslant T\leqslant 1,000$。


题解

首先,将$l$和$r$都转化为二进制。

如果其在二进制下位数不一样,每一位都能是$1$,那么答案一定是$1<<R-1$,其中$R$为$r$的二进制位数。

如果位数相等,从高往低第一个不一样的位往后都可以是$1$,而前面的是什么就只能是什么了。

时间复杂度:$\Theta(T\times\log r)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
long long L,R,ans;
int l[100],r[100],tl,tr;
void get()
{
	tl=tr=ans=0;
	while(L){l[++tl]=(L&1);L>>=1LL;}
	while(R){r[++tr]=(R&1);R>>=1LL;}
}
int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		scanf("%lld%lld",&L,&R);get();
		if(tl==tr)
		{
			int res;
			for(int i=tl;i;i--){if(l[i]!=r[i])break;res=i;}
			ans=(1LL<<(res-1))-1;
			for(int i=res;i<=tl;i++)if(l[i])ans+=(1LL<<(i-1));
		}
		else ans=(1LL<<tr)-1;
		printf("%lld\n",ans);
	}
	return 0;
}

rp++

猜你喜欢

转载自www.cnblogs.com/wzc521/p/11837758.html