luogu P1446 [HNOI2008]Cards

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=100;
int R,B,G,m,M,a[N],n,cnt,b[N],vis[N],f[N][N][N],sum[N];

void init()
{
	scanf("%d %d %d %d %d",&R,&B,&G,&m,&M);
	n=R+B+G;
}

int ksm(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)
			res=1LL*res*a%M;
		b>>=1,a=1LL*a*a%M;
	}
	return res;
}

int C(int x,int y)
{
	int A=1,B=1;
	for (int i=y+1;i<=x;i++)
		A=1LL*A*i%M;
	for (int i=1;i<=x-y;i++)
		B=1LL*B*i%M;
	A=1LL*A*ksm(B,M-2)%M;
	return A;
}

void dfs(int x,int now)
{
	vis[x]=1;
	if(vis[a[x]])
	{
		b[++cnt]=now;
		return;
	}
	dfs(a[x],now+1);
}

void add(int &x,int y)
{
	x=x+y>M?x+y-M:x+y;
}

void work()
{
	int ans=1LL*C(n,R)*C(n-R,B)%M;
	for (int _=1;_<=m;_++)
	{
		for (int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		memset(vis,0,sizeof(vis)),cnt=0;
		for (int i=1;i<=n;i++)
			if(!vis[i])
				dfs(i,1);
//		for (int i=1;i<=cnt;i++)
//			printf("%d ",b[i]);puts("");
		for (int i=1;i<=cnt;i++)
			sum[i]=sum[i-1]+b[i];
		for (int i=0;i<=cnt;i++)
			for (int j=0;j<=R;j++)
				for (int k=0;k<=B;k++)
					f[i][j][k]=0;
		f[0][0][0]=1;
		for (int i=0;i<cnt;i++)
			for (int j=0;j<=R;j++)
				for (int k=0;k<=B;k++)
					if(f[i][j][k])
					{
						if(j+b[i+1]<=R)
							add(f[i+1][j+b[i+1]][k],f[i][j][k]);
						if(k+b[i+1]<=B)
							add(f[i+1][j][k+b[i+1]],f[i][j][k]);
						if(sum[i]-j-k+b[i+1]<=G)
							add(f[i+1][j][k],f[i][j][k]);
					}
		add(ans,f[cnt][R][B]);
	}
	ans=1LL*ans*ksm(m+1,M-2)%M;
	printf("%d\n",ans);
}

int main()
{
	init();
	work();
	return 0;
}
posted @ 2020-05-06 22:19  With_penguin  阅读(108)  评论(0编辑  收藏  举报