1. 程式人生 > >Atcoder Beginner Contest 121 D - XOR World(區間異或和)

Atcoder Beginner Contest 121 D - XOR World(區間異或和)

出了 one href show log 就是 isp () www.

題目鏈接:https://atcoder.jp/contests/abc121/tasks/abc121_d

題目很裸(Atcoder好像都比較裸

就給一個區間求異或和

n到1e12

肯定不能O(n)推

那肯定得通過異或的一些性質

用$f\left( a,b\right)$表示[a,b]區間的異或和

我只觀察出了$f\left( 2^{a},2^{b}-1\right)$的異或和肯定為0。

通過$f\left( 2^{a},2^{a+1}-1\right)$每一位都會出現偶數次

例如 [4,8)

4 : 100

5 : 101

6 : 110

7 : 111

異或和就為0

那麽的$f\left( 2^{a},2^{b}-1\right)$ = $f\left( 2^{a},2^{a+1}-1\right)$ ^ $f\left( 2^{a+1},2^{a+2}-1\right)$ ^ ... ^ $f\left( 2^{b-1},2^{b}-1\right)$ = 0

在這裏參考了大佬的博客https://www.cnblogs.com/Mychael/p/8633365.html原來有結論orz

得到上述結論後 不難得到 $f\left( 0, n\right)$ = $f\left( 2^{k}, n\right)$

分奇偶來看

當n為奇數

那麽$f\left( 2^{k}, n\right)$ k的那一位會出現 n - 2^{k} + 1次 也就是偶數次

那麽最後結果最高位就為0了 $f\left( 2^{k}, n\right) = f\left( 0, n-2^{k}\right)$ 不清楚可以看下上面 4,5,6,7的例子

是不是最高位的1都可以減去了 也就是都減去4 $f\left( 4, 6\right) = f\left( 4 - 4, 6 - 4\right) = f\left( 0, 2\right)$ 沒錯吧!

$f\left( 0, n-2^{k}\right)$ 又可以表示為 $f\left( 0, n‘\right) = f\left( 2^{k-1}, n‘\right)$ 接著推推推

推到最後 到了0~4的範圍裏 為啥到4(2的2次)而不是到2(2的1次)呢

因為上述結論是 $f\left( 2^{a},2^{a+1}-1\right) = 0$ 如果a等於0了 $f\left( 2^{0},2^{1}-1\right) = f\left( 1,1\right) = 1 \neq 0$

所以結論只適用於a >= 1的情況 所以最後應該在0~4裏面確定結論

$n\equiv 1\left( mod4\right)$ 那麽最後還剩最末位一個1 即 $f\left( 0,n\right) =1$

$n\equiv 3\left( mod4\right)$ 那麽最後還有1和3進行異或 最末位就為0了 即 $f\left( 0,n\right) =0$

n為偶數的時候(感覺原博主這部分的推導寫錯了 但結論是對的

假如這個n是2的次冪了 那麽$f\left( 2^{a},n\right) = n$就ok了

如果不是的話 $f\left( 2^{k}, n\right)$ k的那一位會出現 n - 2^{k} + 1次 也就是奇數次 那麽得保留

所以 $f\left( 2^{k}, n\right) = f\left( 0, n-2^{k}\right) Xor 2 ^{k}$ 這次得看$n-2^{k}$是否為2的次冪

是的話就是$f\left( 2^{k}, n\right) = f\left( 0, n-2^{k}\right) Xor 2 ^{k} = n-2^{k} Xor 2 ^{k} = n$

如果一直不是的話 就會把原來的n的每一位都積累起來 最後到$6 - 2^{2} = 2$ 這個時候最後還要異或上1 答案就是n+1

也就是 $n\equiv 0\left( mod4\right)$ $f\left( 0,n\right) =n$

$n\equiv 2\left( mod4\right)$ $f\left( 0,n\right) =n + 1$

總結成程序就是

技術分享圖片
int Xor(int a) {
    if (a % 4 == 0) return a;
    if (a % 4 == 1) return 1;
    if (a % 4 == 2) return a + 1;
    return 0;
}
View Code

答案即為$f\left( a, b\right) = f\left( 0, b\right) Xor f\left( 0, a-1\right)$

代碼如下

技術分享圖片
#include <cstdio>
using namespace std;

long long Xor(long long a) {
    if (a % 4 == 0) return a;
    if (a % 4 == 1) return 1;
    if (a % 4 == 2) return a + 1;
    return 0;
}

int main() {
    long long a, b;
    scanf("%lld%lld", &a, &b);
    printf("%lld", Xor(a -1) ^ Xor(b));
    return 0;
}
View Code

推的過程比較混亂建議手動模擬一遍( ̄▽ ̄)

Atcoder Beginner Contest 121 D - XOR World(區間異或和)