P9443 题解
先考虑经典的
但显然我们无法把二分图建出来跑最大匹配。不过注意到这张图是一张半正则二分图,即所有左部点度数均相等,所有右部点度数也均相等。那么根据著名结论,这张图的最大匹配数等于左右两侧较小的点集大小。证明可以不妨设左边点数更少,则应用霍尔定理,那么从任意一个左部点的子集
有了这个结论就容易做
下面推广到
由于
这样我们设每一类不同的左部点分别有
否则如果是左边的点更少,那么考虑一个左部点的子集
这样我们就证明了此时每个连通块的最大匹配数量等于左右两侧点数量的最小值。而左右两侧点的数量容易
#include <bits/stdc++.h>
#define INF 1000000000
#define LINF 1000000000000000000
#define MOD 1000000007
#define mod 998244353
#define F first
#define S second
#define ll long long
#define N 20
using namespace std;
long double ans=0,tot=0;
ll k,m,a[N],b[N];
void update()
{
ll i,j,l;
long double cur=1,hvs=0;
for(i=0;i<m;i++)
{
for(j=1;j<=b[i];j++)
{
cur*=(double)(a[i]-j+1);
cur/=(double)j;
}
}
tot+=cur;
for(i=0;i<m;i++)
{
if(!b[i])
{
continue;
}
long double nw=1;
for(j=0;j<m;j++)
{
for(l=1;l<=b[j]-(j==i);l++)
{
nw*=(double)(a[j]-l+1);
nw/=(double)l;
}
}
for(j=1;j<k;j++)
{
nw*=(double)j;
}
hvs+=nw;
}
ans+=min(cur,hvs);
return;
}
void dfs(ll x,ll s)
{
if(x==m)
{
if(s==k)
{
update();
}
return;
}
ll i;
for(i=0;i+s<=k&&i<=a[x];i++)
{
b[x]=i;
dfs(x+1,s+i);
}
return;
}
int main(){
ll i;
cin>>k>>m;
for(i=0;i<m;i++)
{
cin>>a[i];
}
dfs(0,0);
printf("%.16Lf\n",ans/tot);
return 0;
}