zoukankan      html  css  js  c++  java
  • [bzoj1004][HNOI2008]Cards

    [bzoj1004][HNOI2008]Cards

    标签: 置换 Burnside引理


    题目链接

    扯淡

    题目中说了这样一句话

    两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)
    

    怎么样?是不是很棘手。然而

    输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。
    

    题意

    n张牌,3种颜色,给你一个置换集合G(且保证对于任意(f,gin G,fg in G)),让你对每张牌染色,使得红色Sred种,蓝色Sblue种,绿色Sgreen种。求不同的染色方案总数。

    题解

    根据burnside引理:等价类的个数等于每一个置换的不动点的个数之和的平均数。
    如果是一个不动点的话,那么这个置换每一个循环中的元素颜色都一样。
    这样我们就能跑一个三维背包了。

    Code

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<queue>
    #include<map>
    #include<stack>
    #include<vector>
    using namespace std;
    #define ll long long
    #define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
    #define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
    #define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
    inline int read()
    {
    	int sum=0,p=1;char ch=getchar();
    	while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
    	if(ch=='-')p=-1,ch=getchar();
    	while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
    	return sum*p;
    }
    
    const int maxn=100;
    
    int mod;
    
    int dp[maxn][maxn][maxn],sr,sb,sg,n,m,ans;
    
    int fa[maxn*3],w[maxn*3],cnt;
    
    int fin(int x)
    {
    	return x==fa[x]?x:fa[x]=fin(fa[x]);
    }
    
    int power(int a,int b)
    {
    	int ans=1;
    	while(b)
    	{
    		if(b & 1)ans=ans*a%mod;
    		b>>=1;
    		a=a*a%mod;
    	}
    	return ans;
    }
    
    void init()
    {
    	sr=read();sb=read();sg=read();n=sr+sb+sg;
    	m=read();mod=read();
    	REP(i,1,m+1)
    	{
    		REP(j,1,n)fa[j]=j;
    		if(i<m+1)
    		{
    			REP(j,1,n)
    			{
    				int v=read();
    				int x=fin(j),y=fin(v);
    				if(x!=y)
    				{
    					fa[y]=x;
    				}
    			}
    		}
    		memset(w,0,sizeof(w));
    		cnt=0;
    		REP(col,1,n)
    		{
    			int flag=1;
    			REP(j,1,n)
    			{
    				if(fin(j)==col)
    				{
    					if(flag)flag=0,cnt++;
    					w[cnt]++;
    				}
    			}
    		}
    		memset(dp,0,sizeof(dp));
    		dp[0][0][0]=1;
    		REP(j,1,cnt)
    		{
    			DREP(x,sr,0)
    			{
    				DREP(y,sb,0)
    				{
    					DREP(z,sg,0)
    					{
    						if(x>=w[j])dp[x][y][z]+=dp[x-w[j]][y][z];
    						if(y>=w[j])dp[x][y][z]+=dp[x][y-w[j]][z];
    						if(z>=w[j])dp[x][y][z]+=dp[x][y][z-w[j]];
    						dp[x][y][z]%=mod;
    					}
    				}
    			}
    		}
    		ans=(ans+dp[sr][sb][sg])%mod;
    	}
    	cout<<ans*power(m+1,mod-2)%mod<<endl;
    }
    
    int main()
    {
    	freopen("input.in","r",stdin);
    	freopen("output.out","w",stdout);
    	init();
    	return 0;
    }
    
    
    
  • 相关阅读:
    Debug权限提升
    QTime的本质上是一个int,QDateTime本质上是一个qint64
    QString先于QObject存在,因为QObject::objectName()返回的是QString
    C++杂记:运行时类型识别(RTTI)与动态类型转换原理
    gcc/g++编译(生动形象,从最容易入手的hello world解释了库的概念)
    分布式存储
    开源代码——Crouton
    android studio
    WebRTC
    FileProvider是个什么东西?
  • 原文地址:https://www.cnblogs.com/gzy-cjoier/p/7472722.html
Copyright © 2011-2022 走看看