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

    题解:burnside引理

    DP出不动点的数目,用burnside引理算等价类

    问题:不明白burnside引理的原理

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int n,m,mm;
    int Sr,Sb,Sg;
    int tot;
    
    int a[100];
    int vis[100];
    int b[100],nn;
    int f[30][30][30];
    void Calc(){
    	nn=0;
    	memset(vis,0,sizeof(vis));
    	memset(f,0,sizeof(f));
    	memset(b,0,sizeof(b));
    	for(int i=1;i<=n;++i){
    		if(vis[i])continue;
    		++nn;
    		int x=i;
    		while(!vis[x]){
    			vis[x]=1;b[nn]++;x=a[x];
    		}
    	}
    //	for(int i=1;i<=nn;++i)cout<<b[i]<<' ';
    //	cout<<endl;
    	f[0][0][0]=1;
    	for(int i=1;i<=nn;++i){
    		for(int x=Sr;x>=0;--x){
    			for(int y=Sb;y>=0;--y){
    				for(int z=Sg;z>=0;--z){
    					int t=b[i];
    					if(x>=t)f[x][y][z]+=f[x-t][y][z];
    					if(y>=t)f[x][y][z]+=f[x][y-t][z];
    					if(z>=t)f[x][y][z]+=f[x][y][z-t];
    					f[x][y][z]%=mm;
    				}
    			}
    		}
    	}
    	tot=(tot+f[Sr][Sb][Sg])%mm;
    }
    
    int Ksm(int a,int p){
    	int ret=1;
    	for(;p;p>>=1,a=a*a%mm){
    		if(p&1)ret=ret*a%mm;
    	}
    	return ret;
    }
    
    int main(){
    	scanf("%d%d%d%d%d",&Sr,&Sb,&Sg,&m,&mm);
    	n=Sr+Sb+Sg;
    	for(int k=1;k<=m;++k){
    		for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    		Calc();
    	}
    	m++;
    	for(int i=1;i<=n;++i)a[i]=i;
    	Calc();
    	cout<<tot*Ksm(m,mm-2)%mm;
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    JAVA中变量的初始化
    取得301转向后的地址
    history for html5
    php traits 介绍
    android 笔记
    C posix 笔记
    笔记
    C 常用库
    cocos2dx:利用CCSpriteBatchNode优化渲染效率
    C实现将指定秒数转化为时:分:秒格式
  • 原文地址:https://www.cnblogs.com/zzyer/p/8455006.html
Copyright © 2011-2022 走看看