牛客网【每日一题】7月30日题目精讲—Xor Path
生活随笔
收集整理的這篇文章主要介紹了
牛客网【每日一题】7月30日题目精讲—Xor Path
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
來源:牛客網:
Xor Path
時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 262144K,其他語言524288K 64bit IO Format: %lld題目描述
給定一棵n個點的樹,每個點有權值A i。定義path(i,j)表示i 到j 的最短路徑上,所有點的點權異或和。
對于i=1~n?1, j=i+1~n,求所有path(i,j)的異或和。
輸入描述:
第一行一個整數n。 接下來n-1行,每行2個整數u,v,表示u,v之間有一條邊。 第n+1行有n個整數,表示每個點的權值A i。
輸出描述:
輸出一個整數,表示所有{\mathbb{path}(i,j)}path(i,j)的異或和,其中 i=1~n?1, j=i+1~n。
示例1
輸入
復制
輸出
復制
題解:
根據異或的性質,一個數異或兩次就沒了,所以一個點異或兩次(偶數次)就相當于沒有。所以我們只需要統計每個點被異或了多少次
我們考慮一下一個點x會有多少種情況:
size[x]表示以x為根的子樹內有多少點
代碼:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; int size[maxn]; int a[maxn],sum; vector<int>g[maxn]; typedef long long ll; int n; void dfs(int u,int fa) {size[u]=1;ll res=0;//記錄奇偶次數 for(auto x:g[u]){if(x==fa)continue;dfs(x,u);size[u]+=size[x];//更新以u為根的樹的大小 res+=1ll*(size[u]-size[x]-1)*size[x];//我們只需要知道奇偶性即可 }res+=1ll*(size[u]-1)*(n-size[u]);//第三種情況 // res>>=1;//多計算了一遍 res+=n-1; //第一種情況 if(res&1)//如果為奇數記入結果 sum^=a[u]; } int main() {cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}for(int i=1;i<=n;i++){cin>>a[i];//點值 }dfs(1,0);//從第一個點開始cout<<sum<<endl;return 0; } #include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; int size[maxn]; int a[maxn],sum; vector<int>g[maxn]; typedef long long ll; int n; void dfs(int u,int fa) {size[u]=1;ll res=0;//記錄奇偶次數 for(auto x:g[u]){if(x==fa)continue;dfs(x,u);res+=1ll*(n-size[x]-1)*size[x];//我們只需要知道奇偶性即可 size[u]+=size[x];//更新以u為根的樹的大小 }res+=1ll*(size[u]-1)*(n-size[u]);//第一和第三種情況 res>>=1;//多計算了一遍 res+=n-1; if(res&1)//如果為奇數記入結果 sum^=a[u]; } int main() {cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}for(int i=1;i<=n;i++){cin>>a[i];//點值 }dfs(1,0);//從第一個點開始cout<<sum<<endl;return 0; }總結
以上是生活随笔為你收集整理的牛客网【每日一题】7月30日题目精讲—Xor Path的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五仁月饼为什么被吐槽
- 下一篇: 牛客网【每日一题】7月31日题目精讲—兔