[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 ...
随机推荐
- OpenGL ES2学习笔记(9)-- 转换矩阵
线性代数是计算机图形学的一块基石,本篇文章总结如何在Shader中使用矩阵来移动.缩放和旋转顶点. 代码和效果 把下面的代码复制到OpenGL Console里: import java.nio.By ...
- linux下64位汇编的系统调用系列
http://blog.csdn.net/mydo/article/category/3084893
- Spring远端调用的实现-Spring Http调用的实现
1:Spring Http设计思想 最近在研究公司自己的一套rpc远程调用框架,看到其内部实现的设计思想依赖于spring的远端调用的思想,所以闲来无事,就想学习下,并记录下. 作为spring远端调 ...
- 关于json中对象的删除
一个json对象在后台产生了,但是有些数据可能无效或者不合法,所以需要在前台作些例外处理,比如删除掉. json的删除有很多种,直接用过 delete json对象方式. 举例如下 Js代码 var ...
- Nginx Resource
Nginx中URL转换成小写首先编译安装nginx_lua_module模块server节: location / { if($uri ~ [A-Z]){ rewrite_by_lua 'return ...
- 7z 压缩命令行工具
命令行压缩解压一 7z 1) 简介7z,全称7-Zip, 是一款开源软件.是目前公认的压缩比例最大的压缩解压软件.主页:http://www.7-zip.org/中文主页:http://7z.spar ...
- Ubuntu12.04中安装ns-allinone-2.34
1.首先安装ns2所需的组件.库之类: $sudo apt-get update $sudo apt-get install build-essential $ tcl8.-dev tk8. tk8. ...
- 一款jquery小插件:实现轻松获取和绑定编辑表单的值(带源码)
实现目的:通常在项目中,编辑页面在前后台需要一个一个框赋值,取值操作,小伙伴们普遍都会感觉繁琐,麻烦.: 实现思路:利用json对象化键值的思想: 好处:方便快速开发,提高开发效率,减少重复性代码: ...
- C++ 实现01背包动态规划
简述一下01背包: 背包容量大小固定,有一些物品,每个物品都有重量和价值两个属性,且物品唯一不重复(即同一物品只能放入一个),放入物品的总重量不能超过背包容量 ,求放入背包的物品的总价值最大化.0代表 ...
- c#中用DirectShow实现媒体播放器的核心(1) DirectShow简介
用.net做多媒体开发的似乎不多,所以网上资源也少,看的人更少.不过我的博客上居然还有几位在等新文章的人,有点出乎我的意料了.目前我已不再从事多媒体相关的工作,加入新公司至今都忙到吐血,再加上害怕水平 ...