(思惟題)HDU - 6121 Build a tree

題意:c++

給一顆K叉樹,統計全部子樹大小的異或和,節點數n和k都小於1e18。spa

 

分析:code

比賽時候一開始被公式搞懵逼了,而後隊友30分鐘就A掉了。blog

昨天本身寫了一下,哇好難寫,各類bug,何時本身的代碼能力這麼弱了- -。遞歸

其實也很簡單,由於n個節點分紅K叉樹,最後一層必然出現三種狀況。it

一種是滿K叉,一種是不滿K叉,還有一種是上一層滿叉。class

只要知道每一層,存在不滿K叉的子樹是第幾叉,而後就能推算出前面滿K叉的數量,和後面不滿K叉的數量。變量

根據異或的性質,判一下奇偶,而後ans異或左邊子樹大小(能夠預處理,也能夠遞歸時候保存)。bug

同理右邊的就是去掉一層的子樹。最後對於中間單獨不滿K叉的,用一個變量統計節點個數便可。統計

(寫的時候,各類bug。返回值沒用longlong找了一個多小時。。。

 

代碼很短:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 long long n, k;
 5 long long ans, dep, du, pw[100];
 6 
 7 long long dfs(long long d, long long tol, long long lotol) {
 8     dep++;
 9     pw[dep - 1] = tol;
10     if(tol >= n) {
11         long long idx = lotol - tol + n - 1;
12         if((idx + 1) & 1)ans ^= 1;
13         du = idx % k + 1;
14         return idx / k;
15     }
16     long long idx = dfs( d + 1, tol + lotol * k, lotol * k);
17     du++;
18     ans ^= du;
19     if(idx & 1)ans ^= pw[dep - d];
20     if((lotol - idx - 1) & 1)ans ^= pw[dep - d - 1];
21     du += (idx % k) * pw[dep - d] + (k - idx % k - 1) * pw[dep - d - 1];
22     return idx / k;
23 }
24 
25 long long xor_n(long long g) {
26     long long t = g & 3;
27     if (t & 1) return t / 2 ^ 1;
28     return t / 2 ^ g;
29 }
30 
31 int main() {
32     int t;
33     scanf("%d", &t);
34     while(t--) {
35         ans = dep = 0;
36         scanf("%lld%lld", &n, &k);
37         if(k == 1) {
38             printf("%lld\n", xor_n(n));
39             continue;
40         }
41         dfs(1, 1, 1);
42         printf("%lld\n", ans);
43     }
44     return 0;
45 }
相關文章
相關標籤/搜索