一个竞赛图,其中m条边,方向为
x−>y(x<y)
x
−
>
y
(
x
<
y
)
的概率是
pi
p
i
,
y−>x
y
−
>
x
的概率是
1−pi
1
−
p
i
,其他边两个方向的概率都是
12
1
2
求强连通分量的期望个数
竞赛图缩点后一定是一条链,前面的点连向后面所有点,我们定义点集
S
S
是这条链的一个前缀当且仅当
那么强连通分量个数等价于缩点后链的前缀
S
S
的个数+1
一种想法是枚举点集,计算这些边的贡献,但
n
n
很大,不能接受
一个大小为
x
x
的前缀,如果连出去的没有特殊边,他的贡献是,每有一条概率为
p
p
的特殊边,贡献乘上
因为
m
m
很小,一个条边的联通块至多
m+1
m
+
1
个点,我们只考虑特殊边,对每个联通块枚举
S
S
里的点,计算有
x
x
<script id="MathJax-Element-21" type="math/tex">x</script>个点在这个联通块里的贡献和
最后再对所有联通块做个背包合并起来
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 50;
const int mod = 998244353;
inline void add(int &a,const int &b){a+=b;if(a>=mod)a-=mod;}
int pw(int x,int k)
{
int re=1;
for(;k;k>>=1,x=(ll)x*x%mod) if(k&1)
re=(ll)re*x%mod;
return re;
}
int inv(int x){ return pw(x,mod-2); }
int n,m,Inv;
int e[maxn][4];
struct edge{int y,i,nex;}a[maxn*maxn]; int len,fir[maxn];
inline void ins(const int x,const int y,const int i){a[++len]=(edge){y,i,fir[x]};fir[x]=len;}
vector<int>V[maxn],Ve[maxn];
int vis[maxn],cnt,id[maxn];
void dfs(const int x)
{
V[vis[x]=cnt].push_back(x); id[x]=(int)V[cnt].size();
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
if(x<y) Ve[cnt].push_back(a[k].i);
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(!vis[y])
dfs(y);
}
int sum[1<<20],g[maxn][maxn];
void Solve(const int now)
{
int vn=(int)V[now].size(),al=1<<vn;
for(int i=0;i<al;i++)
{
int tc=1;
for(int j=0;j<(int)Ve[now].size();j++)
{
int k=Ve[now][j],x=e[k][0],y=e[k][1];
if((i>>(id[x]-1)&1)^(i>>(id[y]-1)&1))
tc=(ll)tc*((i>>(id[x]-1)&1)?e[k][2]:e[k][3])%mod*2ll%mod;
}
sum[i]=sum[i>>1]+(i&1);
add(g[now][sum[i]],tc);
}
}
int f[maxn],temp[maxn];
int main()
{
Inv=inv(10000);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,w; scanf("%d%d%d",&x,&y,&w);
e[i][0]=x,e[i][1]=y; w=(ll)w*Inv%mod;
e[i][2]=w;e[i][3]=(1-w+mod)%mod;
ins(x,y,i); ins(y,x,i);
}
for(int i=1;i<=n;i++) if(!vis[i])
{
++cnt,dfs(i);
Solve(cnt);
}
f[0]=1; int nowsum=0;
for(int i=1;i<=cnt;i++)
{
for(int j=0;j<=nowsum+(int)V[i].size();j++) temp[j]=0;
for(int j=0;j<=nowsum;j++) for(int k=0;k<=(int)V[i].size();k++)
add(temp[j+k],(ll)f[j]*g[i][k]%mod);
nowsum+=(int)V[i].size();
for(int j=0;j<=nowsum;j++) f[j]=temp[j];
}
int ans=0,inv2=inv(2);
for(int i=1;i<nowsum;i++)
add(ans,(ll)f[i]*pw(inv2,i*(nowsum-i))%mod);
add(ans,1);
ans=(ll)ans*pw(10000,n*(n-1))%mod;
printf("%d\n",ans);
return 0;
}