[CLYZ2017]day3

最大割

image

solution

100分

待我学完线性基.

开锁

image

solution

100分

每个点只有一条出边和入边,显然图由很多个环组成.
每个环中必须选出一个点,才能打开所有的箱子.
预处理出每个环的大小,设共\(m\)个,大小为\(g_i\).
\(f[i][j]\)表示前\(i\)个环选了\(j\)个点合法的方案数.
\(f[i][j]=\sum_{l=1}^{g_i}f[i-1][j-l]\times{C_{g_i}^l}\)

\(ans=\frac{f[m][k]}{C_n^k}\).

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 305
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
using namespace std;
typedef long long ll;
int a[N],g[N],n,k,t,cnt;
bool v[N];
double f[N][N],c[N][N];
inline void Aireen(){
	scanf("%d",&t);
	for(int i=0;i<N;++i)
		c[i][0]=1.0;
	for(int i=1;i<N;++i)
		for(int j=1;j<=i;++j)
			c[i][j]=c[i-1][j-1]+c[i-1][j];
	while(t--){
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;++i)
			scanf("%d",&a[i]);
		cnt=0;memset(v,0,sizeof(v));
		for(int i=1;i<=n;++i)
			if(!v[i]){
				v[i]=true;g[++cnt]=1;
				for(int j=a[i];j!=i;j=a[j]){
					v[j]=true;++g[cnt];
				}
			}
		for(int i=1;i<=cnt;++i)
			for(int j=1;j<=cnt;++j)
				f[i][j]=0.0;
		memset(f,0.0,sizeof(f));
		f[0][0]=1.0;
		for(int i=1;i<=cnt;++i){
			for(int j=i,q;j<=k;++j)
				for(int l=min(g[i],j);l>=1;--l)
					f[i][j]+=f[i-1][j-l]*c[g[i]][l];
		}
		printf("%.6lf\n",f[cnt][k]/c[n][k]);
	}
}
int main(){
	freopen("unlock.in","r",stdin);
	freopen("unlock.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2021-11-26 20:20  Aireen_Ye  阅读(31)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.