BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4255 Solved: 2582
[Submit][Status][Discuss]
Description
小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有
多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方
案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.
两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗
成另一种.Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).
Input
第一行输入 5 个整数:Sr,Sb,Sg,m,p(m<=60,m+1<p<100)。n=Sr+Sb+Sg。
接下来 m 行,每行描述一种洗牌法,每行有 n 个用空格隔开的整数 X1X2...Xn,恰为 1 到 n 的一个排列,
表示使用这种洗牌法,第 i位变为原来的 Xi位的牌。输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代
替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。
Output
不同染法除以P的余数
Sample Input
2 3 1
3 1 2
Sample Output
HINT
有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次 可得BRG
和GRB。
100%数据满足 Max{Sr,Sb,Sg}<=20。
Source
这题非常的妙啊。
第一眼看过去应该是P♂lya定理,但是考虑到P♂lya定理是用颜色数做底数计算的,而此题有颜色数的限制,
所以我们考虑它最原始的版本—Burnside引理
这题置换的个数直接给出了($M$)
因此我们只需要求出每个置换中不动点的方案再乘上$M$Z在模$P$意义下的逆元就行了
考虑如何求每个置换中的不动点
联想P♂lya定理。我们在每个循环节中都必须要放同样的颜色,这题也是一样的,只不过多了个数的限制
那么我们直接把个数的限制当做状态dp就行了
设$f[i][a][b]$表示前$i$个循环节,用了$a$个红颜色,$b$个蓝颜色,$c$个黄颜色
转移的时候判断当前放的个数时候大于循环节长度,背包转移
注意最初的状态也算一种方案
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
const int MAXN = 1e5 + ;
using namespace std;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int Sr, Sb, Sg, N, M, mod, change[MAXN];
int f[][][], len[], vis[], num = ; // f[i][j][k]前i个循环节,用了j个红,k个蓝, i - j - k个绿 len[i]第i个循环节有几个元素
int F(int *a) {
memset(f, , sizeof(f));
memset(len, , sizeof(len));
memset(vis, , sizeof(vis));
num = ;
for(int i = ; i <= N; i++) {
if(!vis[i]) {
int cur = i; num++;
while(!vis[i]) len[num]++, vis[i] = , i = a[i];
}
}
f[][][] = ;
for(int i = ; i <= num; i++) {
for(int a = ; a <= Sr; a++) {
for(int b = ; b <= Sb; b++) {
int c = i - a - b, sum = ;
if(c < || c > Sg) continue;
if(a >= len[i]) sum = (sum + f[i - ][a - len[i]][b] ) % mod;
if(b >= len[i]) sum = (sum + f[i - ][a][b - len[i]] ) % mod;
if(c >= len[i]) sum = (sum + f[i - ][a][b]) % mod;
f[i][a][b] = sum % mod;
}
}
}
return f[num][Sr][Sb] % mod;
}
int inv(int a, int p, int mod) {
int base = ;
while(p) {
if(p & ) base = (base * a) % mod;
a = (a * a) % mod; p >>= ;
}
return base % mod;
}
main() {
Sr = read(); Sb = read(); Sg = read(); M = read(), mod = read();
N = Sr + Sb + Sg;
int ans = ;
for(int i = ; i <= M; i++) {
for(int j = ; j <= N; j++) change[j] = read();
ans += F(change);
}
for(int i = ; i <= N; i++) change[i] = i;
ans += F(change);
printf("%d", ans * inv(M + , mod - , mod) % mod);
}
BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)的更多相关文章
- 【bzoj1004】[HNOI2008]Cards Burnside引理+背包dp
题目描述 用三种颜色染一个长度为 $n=Sr+Sb+Sg$ 序列,要求三种颜色分别有 $Sr,Sb,Sg$ 个.给出 $m$ 个置换,保证这 $m$ 个置换和置换 ${1,2,3,...,n\choo ...
- bzoj1004 [HNOI2008]Cards Burnside 引理+背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1004 题解 直接 Burnside 引理就可以了. 要计算不动点的个数,那么对于一个长度为 \ ...
- bzoj1004: [HNOI2008]Cards(burnside引理+DP)
题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染 ...
- BZOJ1004 HNOI2008 Cards Burnside、背包
传送门 在没做这道题之前天真的我以为\(Polya\)可以完全替代\(Burnside\) 考虑\(Burnside\)引理,它要求的是对于置换群中的每一种置换的不动点的数量. 既然是不动点,那么对于 ...
- bzoj1004 [HNOI2008]Cards Burnside定理+背包
题目传送门 思路:首先是Burnside引理,要先学会这个博客. Burnside引理我们总结一下,就是 每种置换下不动点的数量之和除以置换的总数,得到染色方案的数量. 这道题,显然每种 ...
- 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP
题目描述 有\(n\)张卡牌,要求你给这些卡牌染上RGB三种颜色,\(r\)张红色,\(g\)张绿色,\(b\)张蓝色. 还有\(m\)种洗牌方法,每种洗牌方法是一种置换.保证任意多次洗牌都可用这\( ...
- BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )
题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...
- 【BZOJ1004】[HNOI2008]Cards Burnside引理
[BZOJ1004][HNOI2008]Cards 题意:把$n$张牌染成$a,b,c$,3种颜色.其中颜色为$a,b,c$的牌的数量分别为$sa,sb,sc$.并且给出$m$个置换,保证这$m$个置 ...
- luogu P1446 [HNOI2008]Cards burnside引理 置换 不动点
LINK:Cards 不太会burnside引理 而这道题则是一个应用. 首先 一个非常舒服的地方是这道题给出了m个本质不同的置换 然后带上单位置换就是m+1个置换. burnside引理: 其中D( ...
随机推荐
- [PHP]生成随机数(建立字典)
代码如下 : //建立有76个字符组成的字典 $pattern='1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM!@#$% ...
- 如何在smarty模板中执行php代码
Smarty模板主要的目的是分离逻辑层和表现层,所以在模板中不应该包含逻辑部分,逻辑层也不应该含有HTML.要在模板中插入逻辑程序的这种做法"非常"不被推荐,在你的case中. 如 ...
- Js获取移动设备分辨率
在<head>中引入 <meta name="viewport" content="width=device-width, initial-scale ...
- REST面向资源架构 RESTful架构
REST基础概念: 在REST中的一切都被认为是一种资源. 每个资源由URI标识. 使用统一的接口.处理资源使用POST,GET,PUT,DELETE操作类似创建,读取,更新和删除(CRUD)操作. ...
- StringBuilder做函数参数
StringBuilder做函数参数: static void Main(string[] args) { StringBuilder sb = new StringBuilder(); Hello( ...
- Hibernate系列4-----之删除
1.和它的增改查兄弟不同,多了个until包定义了HibernateUntil类,让我们来一起看看吧 public class HibernateUntil { private static Conf ...
- DOS常见命令
dir: 显示一个目录中的文件和子目录 md: 创建目录 rd: 删除目录 cd: 进入指定目录 cd..: 退回到上级目录 cd\: 退回到根目录 del: 删除文件 set: 显示.设置.删除cm ...
- maven课程 项目管理利器-maven 3-3 maven中的坐标和仓库
本节主要讲了两大方面: 1 maven坐标 1.0 构件定义 任何依赖,插件,项目构建输出 都称之为构件. 1.1 maven坐标概念 groupid 公司或组织的域名倒序+当前项目名称 artif ...
- python 生成随机图片验证码
1.安装pillow模块 pip install pillow (1)创建图片 from PIL import Image #定义使用Image类实例化一个长为400px,宽为400px,基于RGB的 ...
- VM(xp系统下用虚拟机安装win8 提示 :units specified don't exist, SHSUCDX can't install)解决方法
改成IDE的模式