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

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ1004

    正解:$Burnside$引理

    解题报告:

      经典$Burnside$引理题。

      考虑一般的$Burnside$引理题都是直接求出一阶循环的个数,然后对于置换个数取平均数。

      但是有颜色限制,所以我们不能直接算。

      而因为一个洗牌方案相当于是一个置换,那么我们就需要求出在这些置换下的不动点个数,因为有颜色限制,而洗牌洗在一个循环中的点必须染成一个颜色,相当于是给每个循环染一个颜色,同时不超过限制数的问题。

      跑一遍三维背包就好了。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #define lc root<<1
    #define rc root<<1|1
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define reg(i,x) for(int i=first[x];i;i=next[i])
    using namespace std;
    typedef long long LL;
    const int MAXN = 61; 
    int Sa,Sb,Sc,n,m,mod,a[MAXN],cnt,size[MAXN];
    int f[MAXN][MAXN][MAXN][MAXN],ans;
    bool vis[MAXN];
    inline int fast_pow(int x,int y){ int r=1; while(y>0) { if(y&1) r=r*x,r%=mod; x=x*x; x%=mod; y>>=1; } return r; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline int dp(int now,int x,int y,int z){
    	if(now==0) return 1;
    	if(f[now][x][y][z]!=-1) return f[now][x][y][z];
    	int tot=0;
    	if(x>=size[now]) tot+=dp(now-1,x-size[now],y,z);
    	if(y>=size[now]) tot+=dp(now-1,x,y-size[now],z);
    	if(z>=size[now]) tot+=dp(now-1,x,y,z-size[now]);
    	tot%=mod; f[now][x][y][z]=tot;
    	return tot;
    }
    
    inline void work(){
    	Sa=getint(); Sb=getint(); Sc=getint(); m=getint(); mod=getint();
    	n=Sa+Sb+Sc; memset(f,-1,sizeof(f));
    	for(int i=1;i<=n;i++) size[i]=1;
    	ans=dp(n,Sa,Sb,Sc);//记得算不动置换类
    	for(int o=1;o<=m;o++) {
    		for(int i=1;i<=n;i++) a[i]=getint();
    		memset(vis,0,sizeof(vis));
    		memset(size,0,sizeof(size));
    		memset(f,-1,sizeof(f));
    		cnt=0;
    		for(int i=1;i<=n;i++) {
    			if(vis[i]) continue;
    			cnt++; for(int j=i;!vis[j];j=a[j]) vis[j]=1,++size[cnt];
    		}
    		ans+=dp(cnt,Sa,Sb,Sc); ans%=mod;
    	}
    	printf("%d",ans*fast_pow(m+1,mod-2)%mod);
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("cards.in","r",stdin);
    	freopen("cards.out","w",stdout);
    #endif
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    HTML学习笔记1
    hadoop的eclipse连接-PC端
    eclipse的菜单栏消失问题解决
    Hadoop的wordcount代码实现
    《机器学习》阅读进度记录
    《金粉世家》
    ubuntu下构建服务器环境-PC 端
    ubuntu安装chrome-PC端
    Discovering-论文
    矩阵取数游戏【NOIP】
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6696879.html
Copyright © 2011-2022 走看看