AGC015D A or...or B Problem

传送门

题意:
从[A,B]中选若干个数(至少1个),进行位运算or,能得到多少个不同的结果。

题解:
考试时想到的离AC特别近,但是就差了一步…亏亏亏。
如果A=B,答案显然是1.所以考虑A<B。
首先我们可以把两个数最前面相同的部分减掉,可以发现这不影响答案(我差的就是这一步)。然后二者之间就一定会有若干个2的次方。根据找规律可以发现,对每一个i,使第i位必须取1,前面为0,后面任取,所以这个i的答案由 [ a , m i n ( b , 2 ∗ i − 1 ) ] [a,min(b,2*i-1)] [a,min(b,2i1)]计算得到。
x &lt; 2 i x&lt;2^i x<2i,那么 [ x , 2 i ) [x,2^i) [x,2i)之间可以得到 2 i − x 2^i-x 2ix个不同的结果。再令 2 i ≤ x &lt; 2 i + 1 2^i\le x\lt 2^i+1 2ix<2i+1,可以发现 [ 2 i , x ] [2^i,x] [2i,x]可以得到的结果有1,2,4,4,8,8,8,8,…的规律。因为一个是从前往后,一个从后往前,所以加起来和 2 i 2^i 2i取min就是当前的i的答案,求和即可。

代码:

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
LL Get(LL l,LL r)
{
	LL tmp=r-l+1,i;
	for(i=1;i<tmp;i*=2ll);
	return i;
}
int main()
{
	LL a,b,t,ans=0;
	scanf("%lld%lld",&a,&b);
	if(a==b) { printf("1\n"); return 0; }
	for(t=1;t<a;t*=2ll);
	while(t>b)
	{
		t/=2;
		if(a&t) a-=t,b-=t;
	}
	ans+=t-a;
	for(;t<=b;t*=2ll) ans+=min(t-a+Get(t,min(2ll*t-1,b)),t);
	printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值