BZOJ 5004: 开锁魔法II

比较显然

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int T,n,K,vis[305],a[305],b[305];
double C[305][305],F[305][305];
int main(){
	scanf("%d",&T);
	C[0][0]=1;
	for (int i=1; i<=300; i++){
		C[i][0]=1;
		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]);
		memset(vis,0,sizeof(vis));
		int cnt=0;
		for (int i=1; i<=n; i++){
			int x=i,sz=0;
			while (!vis[x]){
				vis[x]=1;
				sz++;
				x=a[x];
			}
			if (sz) b[++cnt]=sz;
		}
		memset(F,0,sizeof(F));
		F[0][0]=1;
		for (int i=1; i<=cnt; i++)
			for (int j=1; j<=K; j++)
				for (int k=1; k<=b[i]; k++)
					F[i][j]+=F[i-1][j-k]*C[b[i]][k];
		F[cnt][K]/=C[n][K];
		printf("%.9lf\n",F[cnt][K]);
	}
	return 0;
}

  

posted @ 2019-02-23 21:40  ~Silent  阅读(205)  评论(0编辑  收藏  举报
Live2D