【luogu AT2382】A or...or B Problem(思维)

A or...or B Problem

题目链接:luogu AT2382

题目大意

给你一个区间,问里面的数你至少选一个,可以通过或得到多少个数。

思路

考虑一些东西,至少是二进制。
然后想一下会发现高位一样的都可以当 0,就只用从第一个不一样的地方开始看(如果一样就大小为 1

然后就分割成两个部分的数,考虑分开处理,分别是到 10... 的和从 10... 开始的
然后你会发现就是你往上(就是到 10... 的)的是不会或到小于的值的,所以不会有多的。
然后另外一个自然就是会往上(因为或会让数变大,啊感性一下说变大),那因为你是连续的肯定要的 01 都可以出现或不出现只要你有,所以你出现过 1 的位都可以 01 任选,就也是一个二次方。

然后发现少了,会发现第一个部分(最高位是 0)是可以融入到第二个部分里面的。
(因为你可以选 10...0)使得变成第二部分的。

所以总的来说我们可以总结成若干个区间:
[l,r]
[l+2x,2x+1](往上)
[2x,2x+2y+1]y 是那个 01 的位置的)
然后区间求并即可。

(妈的说的好抽象看代码得了)

代码

#include<cstdio> #include<algorithm> #define ll long long using namespace std; struct node { ll l, r; }p[4]; ll L, R, a[66], b[66]; bool cmp(node x, node y) { if (x.l != y.l) return x.l < y.l; return x.r > y.r; } int main() { scanf("%lld %lld", &L, &R); for (int i = 0; i <= 60; i++) { a[i] = (L >> i) & 1; b[i] = (R >> i) & 1; } if (L == R) {printf("1"); return 0;} for (int i = 60; i >= 0; i--) if (a[i] != b[i]) { L ^= a[i] << i, R ^= b[i] << i; int pl = -1; for (int j = i - 1; j >= 0; j--) if (b[j]) {pl = j; break;} ll l1 = L, r1 = R ^ (1ll << i), l2 = (1ll << i) + L, r2 = (1ll << (i + 1)) - 1; ll l3 = (1ll << i), r3 = (1ll << i) + (1ll << (pl + 1)) - 1; p[1] = (node){l1, r1}; p[2] = (node){l2, r2}; p[3] = (node){l3, r3}; sort(p + 1, p + 3 + 1, cmp); ll ans = 0; ll R = -1; for (int i = 1; i <= 3; i++) {//区间求交 if (p[i].l > R) R = p[i].r, ans += p[i].r - p[i].l + 1; else if (p[i].r > R) ans += p[i].r - R, R = p[i].r; } printf("%lld", ans); return 0; } else L ^= a[i] << i, R ^= b[i] << i; return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_AT2382.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示