zoukankan      html  css  js  c++  java
  • 【BZOJ1004】[HNOI2008]Cards Burnside引理

    【BZOJ1004】[HNOI2008]Cards

    题意:把$n$张牌染成$a,b,c$,3种颜色。其中颜色为$a,b,c$的牌的数量分别为$sa,sb,sc$。并且给出$m$个置换,保证这$m$个置换加上本身的置换能构成一个置换群,两种染色方案被认为是相同的当且仅当一种方案可以通过某个置换变成另一种。求不同的染色方案数。答案对$P$取模。
    $sa,sb,scle 20,mle 60$

    题解:这里对每种颜色都有一个限制,怎么办呢?
    回顾从Burnside引理到Pólya定理的推导过程。
    如果一个染色方案是不动点,那么它的每个循环中的所有元素的颜色都相同。
    所以对于一个置换$f$,我们找到它的一个循环,大小为$k$,我们可以将其看成一个大小为$k$的物品,然后跑多维背包求出方案数,即为不动点的数目。
    最后套用Burnside引理即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    int n,m,sa,sb,sc,P;
    int ans,f[21][21];
    int vis[61],to[61];
    inline int solve()
    {
    	memset(f,0,sizeof(f)),memset(vis,0,sizeof(vis));
    	int i,j,a,b,t;
    	f[0][0]=1;
    	for(i=1;i<=n;i++)	if(!vis[i])
    	{
    		for(t=0,j=i;!vis[j];vis[j]=1,j=to[j],t++);
    		for(a=sa;a>=0;a--)	for(b=sb;b>=0;b--)
    		{
    			if(a>=t)	f[a][b]+=f[a-t][b];
    			if(b>=t)	f[a][b]+=f[a][b-t];
    			f[a][b]%=P;
    		}
    	}
    	return f[sa][sb];
    }
    inline int pw(int x,int y)
    {
    	int z=1;
    	while(y)
    	{
    		if(y&1)	z=z*x%P;
    		x=x*x%P,y>>=1;
    	}
    	return z;
    }
    int main()
    {
    	scanf("%d%d%d%d%d",&sa,&sb,&sc,&m,&P),n=sa+sb+sc;
    	int i,j;
    	for(j=1;j<=m;j++)
    	{
    		for(i=1;i<=n;i++)	scanf("%d",&to[i]);
    		ans+=solve();
    	}
    	for(i=1;i<=n;i++)	to[i]=i;
    	ans+=solve();
    	printf("%d",ans*pw(m+1,P-2)%P);
    	return 0;
    }
    
    
  • 相关阅读:
    git线上操作
    IDEA快捷方式
    Java 四种线程池
    java 获取当前天之后或之前7天日期
    如何理解AWS 网络,如何创建一个多层安全网络架构
    申请 Let's Encrypt 通配符 HTTPS 证书
    GCE 部署 ELK 7.1可视化分析 nginx
    使用 bash 脚本把 AWS EC2 数据备份到 S3
    使用 bash 脚本把 GCE 的数据备份到 GCS
    nginx 配置 https 并强制跳转(lnmp一键安装包)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8227356.html
Copyright © 2011-2022 走看看