等差數列異或和的小規律

背景

異或(xor,運算符號^):按位計算,同0異1,1 ^ 0 = 11 ^ 1 = 0 ,如此。

現定義等差數列 1, 2, ... , n異或和f(n) = 1 ^ 2 ^ ... ^ n ,求f(n)的值。

實現

我們很容易想到質樸的實現如下:

int func(int n) {
    int xor_sum = 0;
    for (int i = 1; i <= n; ++i) {
        xor_sum ^= i;
    }
    return xor_sum;
}

時間複雜度O(n),空間複雜度此處沒有太大必要討論。

通式

聯想到等差數列的四則運算都是有求和公式的,那麼異或運算有沒有呢?直接這麼看也看不出來,先輸出個十來項看看規律:

int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
// 1 3  0 4 1 7  0 8 1 11  0 12 1 15  0 16 1 19

註釋中分別是從第1項到第18項的異或和。這個規律其實非常明顯了,拋開前2個結果不看,後面4個爲一組,定義爲m組,通式如下:

// n=3, 0   n=7, 0      n=4m-1, 0
// n=4, 4   n=8, 8      n=4m, 4m
// n=5, 1   n=9, 1      n=4m+1, 1
// n=6, 7   n=10, 11    n=4m+2, 4m+3

從n>=3開始,後面的異或和的取值都是固定的常量或者公式求得。優化後實現如下:

int func(int n) {
    switch (n) {
        case 1: return 1;
        case 2: return 3;
        default:
            int r = n % 4;
            switch (r) {
                case 0: return r;
                case 1: return 1;
                case 2: return (n - 2) + 3;
                default: return 0;
            }
    }
}

時間複雜度O(1) ,部分代碼爲了體現公式沒有精簡,主要操作就是取餘。

這樣能提升不少性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章