AT2382-[AGC015D]A or...or B Problem

1|0正题

题目链接:https://www.luogu.com.cn/problem/AT2382


1|1题目大意

询问在[L,R]中选取一个或多个数,将它们按位或后能得到多少种不同的结果。

1LR<260


1|2解题思路

我们先把高位的LR都有的1都删除,因为它们之间的数都有这些1,显然没有用。

那么这样LR的最高位就不同了,我们找到R的最高位2k

此时对于[L,2k)中的数字都在L中,而且它们怎么或都不能超过2k,所以这部分的答案就是2kL

然后让这部分的数或上2k,此时我们就有两个部分[2k,R][L+2k,2k1)的数字。

先令L=L+2k1,然后我们分类讨论一下:

  • RL1:此时[2k,2k1)都能直接有。
  • R2k+2k1:此时第k1位为0的数都存在,然后我们让这一部分数或上2k+2k1,那也能得到所有第k1位为1的数,所以同上。
  • L<2k+2k1:此时k1位为1的数都可以得到,继续考虑k1位为0,对k2位同上分类讨论即可。
  • R<2k+2k1,L2k+2k1:此时对于k1位为1的部分我们显然不可能异或出比L小的数字,而比其大的数字都在,所以这部分答案是2kL,对[2k,R]重新做一次上面的操作就好了。

时间复杂度:O(log2n)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; ll A,B,ans; signed main() { scanf("%lld%lld",&A,&B); while(1){ if(B<=1){ ans+=B-A+1; printf("%lld\n",ans); return 0; } ll k=1ll; while(k*2ll<=B)k=k*2ll; if((A&k)&&(B&k)) {A-=k,B-=k,k/=2ll;continue;} ans+=k-A;B-=k;k/=2ll;swap(A,B); while(k){ if(A>B||A>=k){ ans+=k*2ll; printf("%lld\n",ans); return 0; } if(B<k)ans+=k,k/=2ll; else{ ans+=k*2ll-B; B=A;A=0; break; } } } printf("%lld\n",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16557201.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示