题解 AGC015D【A or...or B Problem】

题解 AGC015D【A or...or B Problem】

problem

AB 的整数中选择一个或多个,把这些整数按位或,求一共有多少种可能的结果。

1AB260

solution

首先暴力怎么写呢?FWT。设序列 ai=[LiR],然后对它 FWT-or 之后自己乘几倍,再翻回去。然后输入几组样例,我们可以大概知道是什么东西了。建议输入样例 L=123,R=152。以下说说瞪出来的规律。

首先 L,R 的公共前缀是没有用的,不如删除,这样以后认为 R 的最高位是 1L 的最高位是 0。然后答案显然需要先包括 [L,R],且因为 a|bmax(a,b),所以可能的结果只会更大。

考虑有了 [L,R] 之后能构造 R+1 吗?需要看情况,例如:R=100010012 的时候,显然可以用 100010002100000102 或一下,就是说我们可以去掉 R 的第二个 1,来获得 R+1 的没有第二个 1 的版本,然后或上第二个 1 后面全是零的一个数,构造出 R+1。那么就是说我们的 R 的第二个 1 后面可以全部放满一,不影响答案(如上面的例子可以将 R 直接改为 100011112)。再要更高的位,单靠 R 就无法做到。

考虑 L。举例 L=010111012,R=10001001100011112,我们可以用 [L,100000002) 中的数和 100000002 或一下,获得 [L+100000002,111111112] 中的数。

除此之外没有别的数字,对 [L,R][L+100000002,111111112] 求并就是答案。

根据上面的构造,还可以发现这些可能的结果只需要两个数字或即可。所以 FWT 开平方就够了。

若认为高贵的 __builtin_clzll 是常数复杂度,则整个题的复杂度是常数。不用就是 O(logR)

code

#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
#define bitclz __builtin_clzll
typedef long long LL;
LL getBit(int k) { return 1ll << k; }
bool conBit(LL x, int k) { return x & getBit(k); }
LL L, R;
int main() {
    freopen("or.in", "r", stdin);
    freopen("or.out", "w", stdout);
    scanf("%lld%lld", &L, &R);
    if (L == R) return puts("1"), 0;
    int b = 63 - bitclz(L ^ R);
    assert(conBit(R, b) && !conBit(L, b));
    for (int i = b - 1; i >= 0; i--) if (conBit(R, i)) {
        R |= getBit(i) - 1;
        break;
    }
    LL U = (getBit(b) - 1) | (R >> b << b);
    LL D = L | (R >> b << b);
    if (R < D) printf("%lld\n", R - L + 1 + U - D + 1);
    else printf("%lld\n", U - L + 1);
    return 0;
}

posted @   caijianhong  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示