HDU多校第六场1010
Expectation
Problem Description
You are given an undirected graph consisting of n vertices with m weighted edges. We define the weight of a spanning tree as the bitwise AND of all edges’ weight in spanning tree.
Now select a spanning tree randomly, you should calculate the expected value of the weight of this spanning tree. You are required to print the result mod 998244353. i.e., print x×y−1 mod 998244353 where x×y−1 is the irreducible fraction representation of the result, where y−1 denotes the multiplicative inverse of y modulo 998244353.
Input
The first line is an integer t(1≤t≤10), the number of test cases.
For each test case, there are two space-separated integers n(2≤n≤100) and m(1≤m≤104) in the first line, the number of nodes and the number of edges.
Then follows m lines, each contains three integers u,v,w(1≤u,v,≤n,1≤w≤109,u≠v), space separated, denoting an weight edge between u and v has weight w.
Output
For each test case, output a single line with a single integer, denoting the answer.
Sample Input
1
3 3
1 2 1
1 3 1
2 3 1
Sample Output
1
#include
using namespace std;
const int N=110;
typedef long long LL;
const LL mod = 998244353;
LL ksm(LL a, LL b){
LL s = 1;
while(b){
if(b & 1) s = s * a % mod;
a = a * a % mod;
b >>= 1;
}
return s;
}
int degree[N];
LL C[N][N];
LL det(LL a[][N],int n)//生成树计数:Matrix-Tree定理
{
LL ret=1;
int sign = 0;
for(int i=1; i<n; i++)
{
for(int j=i+1; j<n; j++)
while(a[j][i])
{
// LL t=a[i][i]/a[j][i];
LL t = a[i][i] * ksm(a[j][i], mod - 2) % mod;
for(int k=i; k<n; k++)
a[i][k]=(a[i][k]-a[j][k]*t)%mod;
for(int k=i; k<n; k++)
swap(a[i][k],a[j][k]);
sign ^= 1;
}
if(a[i][i]==0) return 0;
ret=ret*a[i][i]%mod;
}
if(sign) ret *= -1;
if(ret<0) ret += mod;
return ret;
}
int u[10010], v[10010], w[10010];
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--)
{
int n, m;
scanf("%d%d", &n, &m);
memset(C, 0, sizeof C);
memset(degree, 0, sizeof degree);
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &u[i], &v[i], &w[i]);
u[i]--;
v[i]--;
C[u[i]][v[i]]--;
C[v[i]][u[i]]--;
degree[u[i]]++;
degree[v[i]]++;
}
for(int i = 0; i < n; i++) C[i][i] = degree[i];
LL tot = det(C, n), ans = 0;
for(LL val = 1; val <= 1000000000; val <<= 1){
memset(C, 0, sizeof C);
memset(degree, 0, sizeof degree);
for(int i = 1; i <= m; i++){
if(val & w[i]){
C[u[i]][v[i]]--;
C[v[i]][u[i]]--;
degree[u[i]]++;
degree[v[i]]++;
}
}
for(int i = 0; i < n; i++) C[i][i] = degree[i];
ans = (ans + det(C, n) * val) % mod;
}
ans = ans * ksm(tot, mod - 2) % mod;
if(ans < 0) ans += mod;
printf("%lld\n", ans);
}
return 0;
}