結果
問題 | No.1843 Tree ANDistance |
ユーザー |
![]() |
提出日時 | 2022-02-18 21:44:29 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 551 ms / 2,000 ms |
コード長 | 4,021 bytes |
コンパイル時間 | 3,667 ms |
コンパイル使用メモリ | 240,076 KB |
実行使用メモリ | 30,720 KB |
最終ジャッジ日時 | 2024-06-29 08:35:27 |
合計ジャッジ時間 | 14,775 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 38 |
ソースコード
#include <bits/stdc++.h>#include <atcoder/all>using namespace std;using namespace atcoder;const long nPrime = 1000000007;//const long nPrime = 998244353;typedef long long ll;struct UnionFind {vector<int> size, parents;UnionFind() {}UnionFind(int n) {size.resize(n, 1);parents.resize(n, 0);for (int i = 0; i < n; i++) {MakeTree(i);}}void MakeTree(int x) {parents[x] = x;}bool IsSame(int x, int y) { return FindRoot(x) == FindRoot(y); }void Unite(int x, int y) {x = FindRoot(x);y = FindRoot(y);if(x==y){return;}if (size[x] > size[y]) {parents[y] = x;size[x] += size[y];size[y] = -1;} else {parents[x] = y;size[y] += size[x];size[x] = -1;}}int FindRoot(int x) {if (x != parents[x]) parents[x] = FindRoot(parents[x]);return parents[x];}int GetSize(int x){return size[FindRoot(x)];}};const long long nMod = nPrime;class ModInt {long long x;public:ModInt(long long x=0) : x((x%nMod+nMod)%nMod) {}ModInt operator-() const {return ModInt(-x);}ModInt& operator+=(const ModInt& a) {if ((x += a.x) >= nMod) x -= nMod;return *this;}ModInt& operator-=(const ModInt& a) {if ((x += nMod-a.x) >= nMod) x -= nMod;return *this;}ModInt& operator*=(const ModInt& a) {(x *= a.x) %= nMod;return *this;}ModInt operator+(const ModInt& a) const {ModInt res(*this);return res+=a;}ModInt operator-(const ModInt& a) const {ModInt res(*this);return res-=a;}ModInt operator*(const ModInt& a) const {ModInt res(*this);return res*=a;}ModInt Pow(long long t) const {if (!t) return 1;ModInt a = Pow(t>>1);a *= a;if (t&1) a *= *this;return a;}// for prime nModModInt Inv() const {return Pow(nMod-2);}ModInt& operator/=(const ModInt& a) {return (*this) *= a.Inv();}ModInt operator/(const ModInt& a) const {ModInt res(*this);return res/=a;}friend ostream& operator<<(ostream& os, const ModInt& m){os << m.x;return os;}};void MakeTable(vector<ModInt> &viInv, vector<ModInt> &viFctr,vector<ModInt> &viFctrInv, bool bUseFctr = false,const long nTableSize = 1000000){viInv.resize(nTableSize+1, 1);for(long i = 1; i < nTableSize+1; i++){viInv[i] /= i;}if(!bUseFctr){return;}viFctr.resize(nTableSize+1, 1);viFctrInv.resize(nTableSize+1, 1);for(long i = 1; i < nTableSize+1; i++){viFctr[i] = viFctr[i-1] * i;}viFctrInv[nTableSize] /= viFctr[nTableSize];for(long i = nTableSize; i >= 1; i--){viFctrInv[i-1] = viFctrInv[i]*i;}}int main() {long n;cin >> n;vector<pair<pair<long,long>,long>> viEdge(n-1);for(long i = 0; i < n-1; i++){long a,b,c;cin >> a >> b >> c;a--,b--;viEdge[i] = make_pair(make_pair(a,b),c);}ModInt nAns = 0;vector<UnionFind> vzGroup(31,UnionFind(n));for(long i = 0; i <= 30; i++){for(long j = 0; j < n-1; j++){long a = viEdge[j].first.first;long b = viEdge[j].first.second;long c = viEdge[j].second;if((c&(1<<i))!=0){vzGroup[i].Unite(a,b);}}ModInt iThis = 0;for(long j = 0; j < n; j++){if(vzGroup[i].FindRoot(j)==j){ModInt m = vzGroup[i].GetSize(j);iThis += m*(m-1)/2;}}nAns += iThis*(1<<i);}cout << nAns << endl;return 0;}