關於樹上路徑異或和的思考

Harris-H發表於2020-12-25

關於樹上路徑異或和的思考


做樹上路徑異或時突發想到了一個問題,怎麼求樹上路徑異或和之和,但是沒找到題目。

大概思路:

1.樹形 d p dp dp求出從根出發的路徑異或和 d p [ u ] dp[u] dp[u]

2.顯然我們需要的最終結果就是:
∑ d p [ i ] ⊕ d p [ j ] ( 1 ≤ i < j ≤ n ) \sum dp[i]\oplus dp[j] (1\le i<j\le n) dp[i]dp[j](1i<jn)
n ≤ 1 0 5 n\le 10^5 n105 顯然不能暴力。

3.考慮每一位的貢獻。

c n t [ i ] cnt[i] cnt[i]表示第 i i i位出現了多少次 1 1 1,則0出現的次數為 n − c n t [ i ] n-cnt[i] ncnt[i]
由乘法原理,可得到該位的貢獻為: c n t [ i ] × ( n − c n t [ i ] ) × 2 i cnt[i]\times (n-cnt[i])\times 2^i cnt[i]×(ncnt[i])×2i
最後求和可得 a n s = ∑ i = 0 31 c n t [ i ] × ( n − c n t [ i ] ) × 2 i ans=\sum\limits_{i=0}^{31}cnt[i]\times (n-cnt[i])\times 2^i ans=i=031cnt[i]×(ncnt[i])×2i


這個問題還可以有很多變形,比如求路徑異或和為偶數的和,路徑異或和為奇數的和。

對於路徑異或和為奇數,顯然一個 d p [ i ] , d p [ j ] dp[i],dp[j] dp[i],dp[j]最低位不相同即可,所以可以考慮把結點分成兩堆,一堆為奇數,一堆為偶數。
然後開個陣列 a [ ] [ 2 ] , b [ ] [ 2 ] a[][2],b[][2] a[][2],b[][2],再按位計算貢獻。
a n s = ∑ i = 0 31 ( a [ i ] [ 0 ] × b [ i ] [ [ 1 ] + a [ i ] [ 1 ] × b [ i ] [ 0 ] ) × 2 i ans=\sum\limits_{i=0}^{31} (a[i][0]\times b[i][[1]+a[i][1]\times b[i][0])\times 2^i ans=i=031(a[i][0]×b[i][[1]+a[i][1]×b[i][0])×2i

偶數的話,就用上面的答案 − - 去奇數的和,或者還是分成兩堆同理算。


求路徑異或和是 k k k的個數。
開個桶記錄,如果數較大,就用 m a p map map
在這裡插入圖片描述

傳送門


求路徑異或和是 k k k的倍數的個數。

呃,變成點分治題目了。

傳送門

相關文章