厉害题。根本想不到。
Solution
先考虑完美匹配怎么做。
考虑 hall 定理判定,要求 。记 。考虑容斥掉不合法的,对于 的图,选取一个代表元,使得 最大,存在相等时令 最小。
可以证明,这样使得每个没有完美匹配的图,有唯一的代表元 ,所以只会被减一次。假设存在另一个 满足 。如果 与 无交, 更大。否则 与 相交却不包含,设 ,可以得到 。如果取等于号,则 更小,否则 和 中必然有一个比 大。
于是可以设 表示只考虑 和 中的边,满足 ,存在完美匹配的概率; 表示只考虑 和 中的边,满足 ,且此时 是代表元的概率。记 表示 的概率, 表示 和 中无边的概率。
对于 ,总方案数为 ,不合法的是枚举代表元 和 ,此时 不能向 连边, 必须有完美匹配(否则 可以更大)。
对于 ,总方案数为 ,不合法的是枚举更优的代表元 和 ,其余限制与算 时相同。
现在要算所有最大匹配的方案数。最大匹配等于左部点数量减 。
枚举全图的代表元 和 (对于完美匹配则 ),剩下的 也得有完美匹配,额外枚举 表示 与哪些右部点形成完美匹配,此时 不能连向 。
复杂度 。
code
int n,m,e[maxn][maxn],ans;
int no[1<<maxn][1<<maxn],ok[1<<maxn][1<<maxn];
int f[1<<maxn][1<<maxn],g[1<<maxn][1<<maxn];
int sz[1<<maxn];
void work(){
n=read(),m=read();ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)e[i][j]=read()*ni%mod;
}
for(int s=0;s<(1<<n);s++){
for(int t=0;t<(1<<m);t++){
no[s][t]=1;
for(int i=0;i<n;i++)if(s&(1<<i)){
for(int j=0;j<m;j++)if(t&(1<<j))no[s][t]=no[s][t]*(1-e[i][j]+mod)%mod;
}
ok[s][t]=1;
for(int j=0;j<m;j++)if(t&(1<<j)){
ok[s][t]=ok[s][t]*(1-no[s][1<<j]+mod)%mod;
}
}
}
for(int s=0;s<(1<<max(n,m));s++)sz[s]=__builtin_popcount(s);
for(int s=0;s<(1<<n);s++){
for(int t=0;t<(1<<m);t++){
if(sz[s]>sz[t]){
g[s][t]=ok[s][t];
for(int s1=s;s1;s1=(s1-1)&s){
for(int t1=t;;t1=(t1-1)&t){
if((s1!=s||t1!=t)&&sz[s1]-sz[t1]>=sz[s]-sz[t]){
(g[s][t]+=mod-g[s1][t1]*no[s1][t^t1]%mod*f[s^s1][t^t1]%mod)%=mod;
}
if(!t1)break;
}
}
}
else{
f[s][t]=ok[s][t];
for(int s1=s&(s-1);s1;s1=(s1-1)&s){
for(int t1=t&(t-1);;t1=(t1-1)&t){
if(s1!=s||t1!=t)(f[s][t]+=mod-g[s1][t1]*no[s1][t^t1]%mod*f[s^s1][t^t1]%mod)%=mod;
if(!t1)break;
}
}
}
}
}
for(int s=0;s<(1<<n);s++){
for(int t=(1<<m)-1;t;t--){
for(int t1=t&(t-1);;t1=(t1-1)&t){
(f[s][t]+=f[s][t1]*no[s][t^t1])%=mod;
if(!t1)break;
}
}
}
g[0][0]=1;
for(int s=0;s<(1<<n);s++){
for(int t=0;t<(1<<m);t++)if(g[s][t]){
(ans+=g[s][t]*no[s][(1<<m)-1-t]%mod*f[(1<<n)-1-s][(1<<m)-1-t]%mod*(n-(sz[s]-sz[t])))%=mod;
}
}
printf("%lld\n",ans);
}