为了在漫长得飞行旅途中娱乐,Alex和Fedor发明了如下的一个简单的双人游戏。游戏是:
-
首先, Alex画一个有权无向图。该图中可能有多重边(多重边的权值可能相同或者不同)。
-
然后,Fedor选取该图的一个生成树。如果该树是这个图的最小生成树,则Fedor获胜。否则,Alex获胜。
如果两棵树分别包含的边标号形成的两个集合不相同,我们认为这两棵树不同。两个集合A和B,如果至少存在一个元素在A中但不在B中,或者反之,至少存在一个元素在B中但不在A中,则我们认为这两个集合不同。
我们还要指出图拥有太多的生成树会让Alex和Fedor烦乱,于是他们不会用多于$10^{18}$棵生成树的图进行游戏。
现在, Fedor懒得找最小生成树了,于是他会任选一个Alex的图的生成树。每棵生成树被Fedor选择的概率相同。请问此时Fedor获胜的概率是多少?
裸的矩阵树定理,但是这玩意卡精度,卡了我一个多小时……把long double换成__float128就过了,要是还卡估计就得强行取模+CRT了。
#include#include #include #include #define MN 401#define ld __float128#define ll long long#define int long longusing namespace std;int read_p,read_ca,read_f;inline int read(){ read_p=0;read_ca=getchar();read_f=1; while(read_ca<'0'||read_ca>'9') read_f=read_ca=='-'?-1:read_f,read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p*read_f;}struct na{ int x,y,z;}b[MN];bool operator < (na a,na b){ return a.z _abs(b[i][i])) for (k=i;k<=n;k++) swap(b[j][k],b[i][k]); for (j=i+1;j<=n;j++){ ld s=b[j][i]; for (k=i;k<=n;k++) b[j][k]-=b[i][k]/b[i][i]*s; } x*=b[i][i]; } return (ll)(_abs(x)+0.5);}int gf(int x){ return x==fa[x]?x:fa[x]=gf(fa[x]);}inline void add(int x,int y){x=gf(x);y=gf(y);fa[x]=y;}bool cmp(na a,na b){ return gf(a.x)