[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\n",ans);
66     return 0;
67 }
时间: 2024-10-24 21:39:20

[BZOJ1004][HNOI2008]Cards 群论+置换群+DP的相关文章

bzoj1004: [HNOI2008]Cards(burnside引理+DP)

题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染色方案数就是每种置换的不变元素的个数的平均数. 求每种置换的不变元素的个数用背包解决.因为置换之后元素不变,所以对于每个循环节我们要染一个颜色,于是先处理出循环节作为背包中的"物体",然后一个三维背包解决.f[i][j][k]的i j k表示三种颜色分别还可以染多少次. 除m%p用费马小定

BZOJ 1004: [HNOI2008]Cards Polya计数+DP

Polya计数+dp求满足对应循环的不动点有几个 1004: [HNOI2008]Cards Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2046  Solved: 1212 [Submit][Status][Discuss] Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,S

[bzoj1004][HNOI2008][Cards] (置换群+Burnside引理+动态规划)

Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.Sun发现这个问题有点难度,决

BZOJ1004 [HNOI2008]Cards

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! 题目链接:BZOJ1004 正解:$Burnside$引理 解题报告: 经典$Burnside$引理题. 考虑一般的$Burnside$引理题都是直接求出一阶循环的个数,然后对于置换个数取平均数. 但是有颜色限制,所以我们不能直接算. 而因为一个洗牌方案相

【BZOJ】1004: [HNOI2008]Cards(置换群+polya+burnside)

http://www.lydsy.com/JudgeOnline/problem.php?id=1004 学习了下polya计数和burnside引理,最好的资料就是:<Pólya 计数法的应用> --陈瑜希 burnside: $$等价类的个数=\frac{1}{|G|}\sum_{i=1}^{s}D(a_i), a_i \in G$$其中$D(a_i)=a_i置换中染色后不变的方案$ 而polya: $$D(a_i)=k^{C(a_i)},其中C(a_i)是a_i的循环节个数$$证明很简单

BZOJ1004 [HNOI2008]Cards 【burnside定理 + 01背包】

题目链接 BZOJ1004 题解 burnside定理 在\(m\)个置换下本质不同的染色方案数,等于每种置换下不变的方案数的平均数 记\(L\)为本质不同的染色方案数,\(m\)为置换数,\(f(i)\)为置换\(i\)下不变的方案数,那么 \[L = \frac{1}{m}\sum\limits_{i = 1}^{m} f(i)\] 在一个置换下一个方案不变,当且仅当该置换的任意一个循环节内部颜色相同 记循环节个数为\(c_i\),色数为\(k\)且不限使用,那么该置换下不变的方案数为 \[

BZOJ1004 [HNOI2008]Cards(Polya计数)

枚举每个置换,求在每个置换下着色不变的方法数,先求出每个循环的大小,再动态规划求得使用给定的颜色时对应的方法数. dp[i][j][k]表示处理到当前圈时R,B,G使用量为i,j,k时的方法数,背包思想. #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #includ

[BZOJ1004] [HNOI2008]Cards解题报告(Burnside引理)

Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.Sun发现这个问题有点难度,决

[BZOJ1004] [HNOI2008] Cards (Polya定理)

Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.Sun发现这个问题有点难度,决