传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1004

一道好题,但并不是好在融合了三个“考点”(计数,背包dp,逆元),其实背包dp以及求逆元都是小事,重点在于如何计数。

输入数据给出的m种置换是无法构成一个置换群的,因为一个群的定义需要4个性质,即封闭性,结合律,单位元,逆元,根据题目的说法,已经符合了封闭性、结合律、逆元,但是没有单位元,所以需要先添加一个新的置换,对于每个i,a[i] = i。这个置换即为单位元,这样子就构成了置换群。

然后,为什么polya对于本题不适用呢?因为本题规定的颜色数量有限(绿色只有sg个,红色只有sr个,蓝色只有sb个)。若是每种颜色都不限数量的话,因为一个置换的轮换(“轮换”就是一个括号括起来的循环节)必须是同一种颜色,这样才能在置换完成后与置换前相同。然而本题颜色数量有限,怎么办呢?如之前所说,一个轮换必须是同一种颜色,那么我们可以把这个置换的所有轮换列出来,就象这样:

(1, 2, 3), (4, 6), (5, 7), (8, 9, 10, 11), (12)

令C(ai)为置换ai的轮换的数量,既然现在不能简单的3^C(ai) (3是三种颜色),那么就考虑在当前轮换下,有三种决策,一是染成绿色,二是染成红色,三是染成蓝色——这就是一个三维的01背包!之后就简单了,在最后的最后在乘一下置换数m的逆就好了。

#include <cstdio>
#include <cstring> int n, m, p, sr, sb, sg, a[65][65], ans, f[25][25][25], siz[65], cnt;
char book[65]; inline int cal(int * cir) {
memset(f, 0, sizeof f);
f[0][0][0] = 1;
memset(book, 0, sizeof book);
cnt = 0;
for (int i = 1; i <= n; ++i) {
if (!book[i]) {
++cnt;
book[i] = 1;
siz[cnt] = 1;
for (int j = cir[i]; j != i; j = cir[j]) {
book[j] = 1;
++siz[cnt];
}
}
}
for (int i = 1; i <= cnt; ++i) {
for (int jr = sr; ~jr; --jr) {
for (int jb = sb; ~jb; --jb) {
for (int jg = sg; ~jg; --jg) {
if (jr >= siz[i]) {
f[jr][jb][jg] = (f[jr][jb][jg] + f[jr - siz[i]][jb][jg]) % p;
}
if (jb >= siz[i]) {
f[jr][jb][jg] = (f[jr][jb][jg] + f[jr][jb - siz[i]][jg]) % p;
}
if (jg >= siz[i]) {
f[jr][jb][jg] = (f[jr][jb][jg] + f[jr][jb][jg - siz[i]]) % p;
}
}
}
}
}
return f[sr][sb][sg];
}
inline int poww(int di, int mi) {
int i, rt;
for (i = 31; mi >> i & 1 ^ 1; --i);
rt = di;
for (--i; ~i; --i) {
rt = rt * rt % p;
if (mi >> i & 1) {
rt = rt * di % p;
}
}
return rt;
} int main(void) {
//freopen("in.txt", "r", stdin);
scanf("%d%d%d%d%d", &sr, &sb, &sg, &m, &p);
n = sr + sb + sg;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
scanf("%d", a[i] + j);
}
}
++m;
for (int j = 1; j <= n; ++j) {
a[m][j] = j;
} for (int i = 1; i <= m; ++i) {
ans = (ans + cal(a[i])) % p;
}
printf("%d\n", ans * poww(m, p - 2) % p);
return 0;
}

  

bzoj1004 [HNOI2008]Cards【Burnside/Polya】的更多相关文章

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

    题目链接 BZOJ1004 题解 burnside定理 在\(m\)个置换下本质不同的染色方案数,等于每种置换下不变的方案数的平均数 记\(L\)为本质不同的染色方案数,\(m\)为置换数,\(f(i ...

  2. [BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】

    题目链接:BZOJ - 1004 题目分析 首先,几个定义和定理引理: 群:G是一个集合,*是定义在这个集合上的一个运算. 如果满足以下性质,那么(G, *)是一个群. 1)封闭性,对于任意 a, b ...

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

    Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...

  4. bzoj1004 [HNOI2008]Cards 置换群+背包

    [bzoj1004][HNOI2008]Cards 2014年5月26日5,3502 Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿 ...

  5. BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )

    题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...

  6. 【Burnside定理】&【Pólya定理】

    Burnside & Pólya (详细内容请参阅<组合数学>或2008年cyx的论文,这里只写一些我学习的时候理解困难的几个点,觉得我SB的请轻鄙视……如果有觉得不科学的地方欢迎 ...

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

    http://www.lydsy.com/JudgeOnline/problem.php?id=1004 学习了下polya计数和burnside引理,最好的资料就是:<Pólya 计数法的应用 ...

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

    Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...

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

    Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...

随机推荐

  1. C++ STL, next_permutation用法。

    next_permutation 将按字母表顺序生成给定序列的下一个较大的序列,直到整个序列为 #include"iostream" #include"algorithm ...

  2. ACM学习历程—UESTC 1218 Pick The Sticks(动态规划)(2015CCPC D)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1218 题目大意就是求n根木棒能不能放进一个容器里,乍一看像01背包,但是容器的两端可以溢出容器,只要两端的木 ...

  3. VC6++常用快捷键

    VC6快捷键大全(转载) VC6快捷键大全,记在这里,方便查阅.F1: 帮助Ctrl+O :OpenCtrl+P :PrintCtrl+N :NewCtrl+Shift+F2 :清除所有书签F2 :上 ...

  4. Hibernate Validator--创建自己的约束规则

    尽管Bean Validation API定义了一大堆标准的约束条件, 但是肯定还是有这些约束不能满足我们需求的时候, 在这种情况下, 你可以根据你的特定的校验需求来创建自己的约束条件. 3.1. 创 ...

  5. inner join ,left join ,right join区别

    inner join ,left join ,right join区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中 ...

  6. 关于KMeans的评价及聚簇结果的得到

    import numpy as npfrom sklearn.cluster import KMeansfrom sklearn import metricsimport matplotlib.pyp ...

  7. CentOS 7 配置 samba服务器

    一.在服务器端上安装软件并进行相关配置(以下操作需用用户root进行): 1.安装samba: yum -y install samba samba-client 2.启动服务并设置开机启动: sys ...

  8. 编写html页面时常见的问题(转)

    编写html页面时常见的问题(一)   说到写页面,肯定有很多人在刚接触编写页面这一块时遇到很多细节和兼容性的问题,那么在这里我总结一些经常遇到的小问题.希望能够帮助学习页面搭建的初学者! 虽然说ie ...

  9. base64 数据加密

    1.新建一个base64.js文件 添加下面的代码 /* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp> * Version: 1.0 ...

  10. [原创]SQL表值函数:获取从当月计算起往前自定义月份数

      今天我现在发现看一篇博文不能够太长,只要能够描述清楚自己想表达的东西,能够让大家知道你要讲什么就行了.因为我今天看了一些长篇博文,真的觉得知识点太多了, 会让人囫囵吞枣. 这篇博文跟我昨天发表的类 ...