zoukankan      html  css  js  c++  java
  • [BZOJ1004][HNOI2008]Cards 群论+置换群+DP

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1004

    首先贴几个群论相关定义和引理。

    群:G是一个集合,*是定义在这个集合上的一个运算。

    如果满足以下性质,那么(G, *)是一个群。

    1)封闭性,对于任意 a, b 属于 G, a * b 属于 G

    2)结合律, a * b * c = a * (b * c)

    3)单位元,在 G 中存在一个单位元 e ,使得对于 G 中任意的 a , a * e = e * a = a

    4)逆元, 对于 G 中任意的 a ,在 G 中存在 b , 使得 a * b = e , 其中 b 叫做 a 的逆元

    比如在模一个数意义下的整数加法就是一个群。

    满足交换律的群是交换群,又叫阿贝尔群。

    置换:可以用 (a1 -> b1, a2 -> b2, ... , an -> bn) 表示一个置换,其中 a1, ... , an 和 b1, ..., bn 都是1 到 n 的一个排列;

    如果一些置换和它们的叠加运算构成一个群,就把它们叫做一个置换群。

     

    在置换群中的 Burnside 引理:如果按照一定要求,要对1到n 的位置染色,那么本质不同的染色方案数为置换群中每个置换的不动染色方案数的平均数。

    来解释以下,本质不同的染色方案是指,两个染色方案不能通过置换群中的任意置换变换使其相同,那么它们就是本质不同的。

    某个置换的不动染色方案数是指,用这个置换变换之后没有发生变化的染色方案。

     

    那么我们就是要求出每个置换的不动染色方案数。

    Polya定理,如果是用k种颜色染色,那么对于置换 P 来说,它的不动染色方案数为 k^(L(P)), 其中L(P)为置换P的循环节数。

    由于这道题中有颜色数目的限制,我们不能直接套Polya定理,但是可以把每个循环节当作一种物品,用背包求方案数。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int inline readint(){
     6     int Num;char ch;
     7     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
     8     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
     9     return Num;
    10 }
    11 int Sr,Sb,Sg,n,m,mod;
    12 int quick_pow(int x,int y){
    13     int base=x,sum=1;
    14     while(y){
    15         if(y&1) sum=sum*base%mod;
    16         base=base*base%mod;
    17         y>>=1;
    18     }
    19     return sum;
    20 }
    21 int fm[65][65],cnt[65],f[65/3][65/3][65/3];
    22 bool vis[65];
    23 int dp(int x){
    24     int tot=0;
    25     memset(vis,false,sizeof(vis));
    26     memset(cnt,0,sizeof(cnt));
    27     memset(f,0,sizeof(f));
    28     for(int i=1;i<=n;i++){
    29         if(!vis[i]){
    30             int j=i;
    31             tot++;
    32             while(!vis[fm[x][j]]){
    33                 vis[fm[x][j]]=true;
    34                 cnt[tot]++;
    35                 j=fm[x][j];
    36             }
    37         }
    38     }
    39     f[0][0][0]=1;
    40     for(int i=1;i<=tot;i++)
    41         for(int j=Sr;j>=0;j--)
    42             for(int k=Sb;k>=0;k--)
    43                 for(int t=Sg;t>=0;t--){
    44                     if(j>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j-cnt[i]][k][t])%mod;
    45                     if(k>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j][k-cnt[i]][t])%mod;
    46                     if(t>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j][k][t-cnt[i]])%mod;
    47                 }
    48     return f[Sr][Sb][Sg];
    49 }
    50 int main(){
    51     Sr=readint();
    52     Sb=readint();
    53     Sg=readint();
    54     m=readint();
    55     mod=readint();
    56     n=Sr+Sb+Sg;
    57     for(int i=1;i<=m;i++)
    58         for(int j=1;j<=n;j++)
    59             fm[i][j]=readint();
    60     m++;
    61     for(int i=1;i<=n;i++) fm[m][i]=i;
    62     int ans=0;
    63     for(int i=1;i<=m;i++) ans+=dp(i);
    64     ans=ans*quick_pow(m,mod-2)%mod;
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
  • 相关阅读:
    Hash碰撞 & 拒绝服务漏洞
    Java: 在不同windows主题下,JFrame窗口设置最佳高度的解决方案
    java: 关于从jar中读取资源遇到的问题getClass().getResource(...)
    Windows 服务程序、窗口界面、桌面交互、与远程桌面
    MySQL用户与权限管理
    Linux 用户与用户组
    书单整理
    2013年个人工作与学习总结
    Raphaël.js学习笔记
    Ant学习笔记(2) 在Eclipse中使用Ant
  • 原文地址:https://www.cnblogs.com/halfrot/p/7481690.html
Copyright © 2011-2022 走看看