跳转至

区间数位运算

按位与

\(ans=L\&(L+1)\&…\&R\)

为二进制位最长公共前缀,其余位为 \(0\)

C++
1
2
3
4
5
6
7
8
i64 sand(i64 L, i64 R) {
    for (int i = 0 ; i <= 62 ; i++) {
        if ((L >> i) == (R >> i)) {
            return L >> i << i;
        }
    }
    return -1;
}

按位或

\(ans=L|(L+1)|…|R\)

为二进制位最长公共前缀,其余位为 \(1\)

C++
1
2
3
4
5
6
7
8
i64 sor(i64 L, i64 R) {
    for (int i = 0 ; i <= 62 ; i++) {
        if ((L >> i) == (R >> i)) {
            return L | ((1LL << i) - 1);
        }
    }
    return -1;
}

按位异或

\(ans=L\oplus(L+1)\oplus…\oplus R\)

打表出规律

C++
i64 sxor(i64 x) {
    int t = x % 4;
    if (t == 0) {
        return x;
    }
    if (t == 1) {
        return 1;
    }
    if (t == 2) {
        return x + 1;
    }
    return 0;
}
i64 sxor(i64 L, i64 R) {
    return sxor(L - 1) ^ sxor(R);
}
例题

算数大师 - 计蒜客