[BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】
题目链接:BZOJ - 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的循环节数。
这个很好理解,因为每个循环节如果要使置换之后不改变的话,应该使这个循环节中都染同一种颜色。
但是,这道题的染色要求是给定了3种颜色的数量,就不能用 k^(L(P)) 来求了。
我们使用一种3维DP,还是先搜索一遍求出这个置换的所有循环节的大小。然后把每个循环节看作一个物品,染一种颜色。
用 f[i][j][k] 表示染了前 i 件物品,第1种颜色用了 j 个, 第2种颜色用了 k 次的染色方案数。
这道题还需要注意的一点是,需要加上一个不做任何改变的置换作为单位元才能成为一个置换群。
这个单位元的不动染色方案数就是所有的染色方案数,直接用多重集排列就好了, n! / (a! b! c!)。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; const int MaxN = 60; int Na, Nb, Nc, n, m, Mod, Ans, Top;
int A[MaxN], V[MaxN], Sum[MaxN], f[MaxN][MaxN][MaxN]; bool Used[MaxN]; inline int Pow(int a, int b)
{
int ret = 1, f = a;
while (b)
{
if (b & 1)
{
ret *= f;
ret %= Mod;
}
b >>= 1;
f *= f;
f %= Mod;
}
return ret;
} inline int NY(int x) {return Pow(x, Mod - 2);} void DFS(int x, int Num)
{
if (Used[x])
{
V[++Top] = Num;
return;
}
Used[x] = true;
DFS(A[x], Num + 1);
} inline int Fac(int x)
{
int ret = 1;
for (int i = 1; i <= x; ++i)
{
ret *= i;
ret %= Mod;
}
return ret;
} int main()
{
scanf("%d%d%d%d%d", &Na, &Nb, &Nc, &m, &Mod);
n = Na + Nb + Nc;
Ans = Fac(n) * NY(Fac(Na)) % Mod * NY(Fac(Nb)) % Mod * NY(Fac(Nc)) % Mod;
for (int i = 1; i <= m; ++i)
{
for (int j = 1; j <= n; ++j)
{
scanf("%d", &A[j]);
Used[j] = false;
}
Top = 0;
for (int j = 1; j <= n; ++j)
if (!Used[j]) DFS(j, 0);
Sum[0] = 0;
for (int j = 1; j <= Top; ++j)
Sum[j] = Sum[j - 1] + V[j];
f[0][0][0] = 1;
for (int j = 1; j <= Top; ++j)
{
for (int p = 0; p <= Na; ++p)
{
for (int q = 0; q <= Nb; ++q)
{
f[j][p][q] = 0;
if (p >= V[j])
{
f[j][p][q] += f[j - 1][p - V[j]][q];
f[j][p][q] %= Mod;
}
if (q >= V[j])
{
f[j][p][q] += f[j - 1][p][q - V[j]];
f[j][p][q] %= Mod;
}
if ((Sum[j] - p - q) >= V[j])
{
f[j][p][q] += f[j - 1][p][q];
f[j][p][q] %= Mod;
}
}
}
}
Ans += f[Top][Na][Nb];
Ans %= Mod;
}
Ans *= NY(m + 1);
Ans %= Mod;
printf("%d\n", Ans);
return 0;
}
[BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】的更多相关文章
- BZOJ 1004 HNOI2008 Cards Burnside引理
标题效果:特定n张卡m换人,编号寻求等价类 数据保证这m换人加上置换群置换后本身构成 BZOJ坑爹0.0 条件不那么重要出来尼玛怎么做 Burnside引理--昨晚为了做这题硬啃了一晚上白书0.0 都 ...
- bzoj1004: [HNOI2008]Cards(burnside引理+DP)
题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染 ...
- BZOJ 1004: [HNOI2008]Cards [Polya 生成函数DP]
传送门 题意:三种颜色,规定使用每种颜色次数$r,g,b$,给出一个置换群,求多少种不等价着色 $m \le 60,\ r,g,b \le 20$ 咦,规定次数? <组合数学>上不是有生成 ...
- BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )
题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...
- bzoj 1004 1004: [HNOI2008]Cards burnside定理
1004: [HNOI2008]Cards Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1668 Solved: 978[Submit][Stat ...
- bzoj1004 [HNOI2008]Cards Burnside 引理+背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1004 题解 直接 Burnside 引理就可以了. 要计算不动点的个数,那么对于一个长度为 \ ...
- BZOJ 1004 Cards(Burnside引理+DP)
因为有着色数的限制,故使用Burnside引理. 添加一个元置换(1,2,,,n)形成m+1种置换,对于每个置换求出循环节的个数, 每个循环节的长度. 则ans=sigma(f(i))/(m+1) % ...
- 【bzoj1004】[HNOI2008]Cards Burnside引理+背包dp
题目描述 用三种颜色染一个长度为 $n=Sr+Sb+Sg$ 序列,要求三种颜色分别有 $Sr,Sb,Sg$ 个.给出 $m$ 个置换,保证这 $m$ 个置换和置换 ${1,2,3,...,n\choo ...
- BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4255 Solved: 2582[Submit][Status][Discuss] Descript ...
随机推荐
- Linux性能及调优指南(翻译)
http://blog.csdn.net/ljianhui/article/details/46718835 http://blog.chinaunix.net/uid-26000296-id-406 ...
- QT实现多语言切换
功能需求: 网盘客户端要能够实现多国语言的切换,第一版要支持中.英文的切换.在实现过程中感觉QT对多国语言的支持还是很不错的,制作多语言包很方便,切换的逻辑也很简单.下面就来看一下QT中如何制作多语言 ...
- 使用内省方式操作JavaBean
内省,英文中称作introspector.主要对javaBean进行操作,JavaBean是一个特殊的Java类,该类中方法名符合特定的规则(其实就是getXXX,setXXX),我们一般是利用get ...
- Property工具类,Properties文件工具类,PropertiesUtils工具类
Property工具类,Properties文件工具类,PropertiesUtils工具类 >>>>>>>>>>>>>& ...
- python: pandas模块
10分钟入门 pandas 评:我跟作者的智商差距是有多大,才能让我用60分钟看完作者认为10分钟的内容... 详细内容见 Cookbook 习惯上我们先导入 : In [1]: import pan ...
- js去掉所有空格
<script> String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g ...
- MySQL Workbench 6.3 CE 不显示MySql、infomation_schema等数据库
MySQL Workbench 6.3 CE 不显示MySql.infomation_schema等数据库 通过修改偏好设置可显示: 1.Edit-->Preferences....-----& ...
- linux rman shell
# make direcory for backset file and scripts file,in my case /backup/db_bak cd /backup/db_bak mkdi ...
- rac中 kull session会话脚本
方法:ALTER SYSTEM KILL SESSION '80, 6, @2'; --<= 80 sid,6 serial#,@2 inst_id kill session 脚本如下:sel ...
- 自定义Operation
1.要自定义一个Operation 首先要创建一个继承于NSOperation的类. 2.在创建好的类的.h文件声明自定义的方法:-(instancetype)initWithDownLoadMess ...