CF724G Xor-matic Number of the Graph
阿新 • • 發佈:2020-09-15
給你一個無向圖,有n個頂點和m條邊,每條邊上都有一個非負權值。
我們稱一個三元組 \((u,v,s)\) 是有趣的,當且僅當對於 \(u,v\in [1,n]\) ,有一條從 \(u\) 到 \(v\) 的路徑(可以經過相同的點和邊多次),其路徑上的權值異或和為 \(s\) 。對於一條路徑,如果一條邊經過了多次,則計算異或和時也應計算多次。不難證明,這樣的三元組是有限的。
計算所有有趣的三元組中 \(s\) 的和對於 \(10^9+7\) 的模數
首先考慮如何計算答案,列舉每一條簡單路徑(可以寫成\(dis_u\oplus dis_v\),\(dis\)表示到\(1\)
而這樣子並不容易做,我們注意到線性基的一個性質。
假設該線性基的元素個數為\(cnt\)個,那麼該線性基可以表示\(2^{cnt}\)個不同的數,而如果線性基的第\(x\)位為\(1\),那麼有\(2^{cnt-1}\)個數的第\(x\)為\(1\)。
這啟發我們去對每一位分開考慮計算貢獻。
如果線性基第\(x\)位為\(1\),那麼不管\(u,v\)怎麼選都能使異或和第\(x\)位為\(1\),那麼貢獻為\(2^x2^{cnt-1}\begin{pmatrix}n\\2\end{pmatrix}\)。
如果線性基第\(x\)位不為\(1\),那麼找到\(dis_u\)
Code
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> const int N = 2e5; const int P = 1e9 + 7; using namespace std; struct edges { int to; long long cost; }edge[N * 2 + 5]; int n,m,head[N + 5],nxt[N * 2 + 5],edge_cnt,vis[N + 5],cnt,ans,nn,sm[100]; long long dis[N + 5],p[100]; void add_edge(int u,int v,long long w) { edge[++edge_cnt] = (edges){v,w}; nxt[edge_cnt] = head[u]; head[u] = edge_cnt; } void ins(long long x) { for (int i = 62;i >= 0;i--) if (x >> i & 1) { if (!p[i]) { p[i] = x; cnt++; break; } x ^= p[i]; } } void dfs(int u,long long cnt) { vis[u] = 1; nn++; dis[u] = cnt; for (int i = 62;i >= 0;i--) if (dis[u] >> i & 1) sm[i]++; for (int i = head[u];i;i = nxt[i]) { int v = edge[i].to; long long w = edge[i].cost; if (!vis[v]) dfs(v,cnt ^ w); else ins(dis[u] ^ dis[v] ^ w); } } void calc(int st) { memset(p,0,sizeof(p)); memset(sm,0,sizeof(sm)); cnt = 0; nn = 0; dfs(st,0); for (int i = 62;i >= 0;i--) { int fl = 0; for (int j = 62;j >= 0;j--) if (p[j] >> i & 1) { fl = 1; break; } if (fl) ans += 1ll * nn * (nn - 1) / 2 % P * ((1ll << i) % P) % P * ((1ll << cnt - 1) % P) % P,ans %= P; else ans += (1ll << cnt) % P * ((1ll << i) % P) % P * sm[i] % P * (nn - sm[i]) % P,ans %= P; } } int main() { scanf("%d%d",&n,&m); int u,v; long long w; for (int i = 1;i <= m;i++) { scanf("%d%d%lld",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } for (int i = 1;i <= n;i++) if (!vis[i]) calc(i); cout<<ans<<endl; return 0; }