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

Posted wzc521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CSP-S模拟测试]:最大或(数学)相关的知识,希望对你有一定的参考价值。

题目传送门(内部题141)


输入格式

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


输出格式

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


样例

样例输入:

3
1 10
1023 1024
233 322

样例输出:

15
1023
511


数据范围与提示

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


题解

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

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

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

时间复杂度:$Theta(T imeslog 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
",ans);
	}
	return 0;
}

rp++

以上是关于[CSP-S模拟测试]:最大或(数学)的主要内容,如果未能解决你的问题,请参考以下文章

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

[CSP-S模拟测试]:小P的生成树(数学+Kruskal)

[CSP-S模拟测试]:画作(BFS+数学)

[CSP-S模拟测试]:数列(数学)

[CSP-S模拟测试]:装饰(数学)

[CSP-S模拟测试]:神炎皇(数学)