題目連結:
給定一二進位制正整數 L (1 ≦ 其在十進位制下的值 ≦ 2 ^ 923, 000,且沒有前導 0 ),求有多少對(a, b)數對滿足:
a + b ≦ L 且
a XOR b = a + b
由於答案可能很大,請將答案取除以 10 ^ 9 + 7 之後的餘數。
第一筆:
10
第二筆:
1111111111111111111
第三筆:
1
我們先觀察如果數對 (a, b) 滿足 a + b = L ,有多少數對 (a, b) 滿足 a + b = a XOR b 。而我們可以發現其即跟 L 中有多少的 1 有關,設其 1 的數量為 C 。則有 2 ^ C 個數對滿足要求。因為每個「1」可以分給 a 或是 b 。
接著推廣成題目的樣子就是把所以對於 a + b = N (0 ≦ N ≦ L),求每個 N 中 1 的數量 CN 並將所有值加總起來。但是直接做當然會超時(L 值太大了)。
因此,我們需要可以快速統計 ≦ L 的數字中 2 ^ CN 之總和的方法。有一方法如下所示:
設我們現在的L值為 b0 b1 b2 …… bn-1 (每個 bi 代表 L 中的一個位數),因此 b0 一定為 1 所以以 b0 為例:
我們可以發現 ≦ 1 0 0 …… 0 的數字有 2 ^ (n-1) 個,而它們的 2 ^ CN 總和為
而上式即為 (2 + 1) ^ (n - 1) 的二項式展開,所以值為 3 ^ (n - 1) 。
而接著如果 b1 也為 1 ,則結果也類似 b0 的情況,但是這次 ≦ b0 1 0 …… 0 有 2 ^ (n - 2)且計算 2 ^ CN 的總和考慮前面有的「1」之數量(對於 b1 來說,有 b0 這1 個「1」),因此代入上式後算出來的 2 ^ CN 之總和應為
3 ^ (n - 2 ) × 2
推廣一下,可得通式:
bi × 3 ^(n - i - 1) × 2 ^ Oi
其中, Oi 代表 bi 的左邊位數有多少個「1」(不過不包含 bi 自己)。
因此,由左至右掃過 L 的位元即可求得解答。至於要快速地算出 3 的次方,可以使用「快速冪」的技巧,詳情參見本人
一年前的文章。
但是由於上面的算法不會考慮到 a + b = L 的情況,因此還要再將其值加入答案裡,即 2 ^ Oi 。
另外,上面的每個運算之後都要記得取 10 ^ 9 + 7 的餘數。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。