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( ...
 
随机推荐
- c#操作excel的一些记录
			
//开启Excel APP Excel.Application xlApp = new Excel.Application(); //获取程序下bin—>debug下的文件 ...
 - JDBC之Java连接mysql实现增删改查
			
使用软件:mysql.eclipse 链接步骤: 1.注册驱动 2.创建一个连接对象 3.写sql语句 4.执行sql语句并返回一个结果或者结果集 5.关闭链接(一般就是connection.stat ...
 - windows server2008 64 asp.net 使用office组件环境配置.
			
服务器是windows server2008 64位系统, 我的系统需要用到Microsoft.Office.Interop.Excel组件 在上传Excel单据遇到错误:检索 COM 类工厂中 CL ...
 - python反爬之网页局部刷新1
			
# ajax动态加载网页 # 怎样判断一个网页是不是动态加载的呢? # 查看网页源代码,如果源码中没有你要的数据,尝试访问下一页,当你点击下一页的时候,整个页面没有刷新, 只是局部刷新了,很大的可能是 ...
 - pc端的企业网站(IT修真院test8)详解1-4
			
今天完成的事情:(1,伪元素:before,:after的使用.2.table的使用(collapse的使用)3rgba的高级运用) 今天我主要完成test8-3的页面. header和footer都 ...
 - atom markdown转换PDF 解决AssertionError: html-pdf: Failed to load PhantomJS module
			
atom编辑器markdown转换PDF 解决AssertionError: html-pdf: Failed to load PhantomJS module. You have to set th ...
 - ARouter使用随记
			
官方文档地址 其他配置 1.创建一个config.gradle ext{ isDebug = false //false:作为Lib集成存在, true:作为application组件存在 andro ...
 - SAP ECC6.0-中建信息版
			
平台: SUSE Enterprise Server 类型: 虚拟机镜像 软件包: sap ecc 6.0 ehp7 sps10 commercial erp sap 服务优惠价: 按服务商许可协议 ...
 - 用SQL将数字转换为中文数字
			
IF OBJECT_ID('fn_GetChnNum') IS NOT NULL BEGIN DROP FUNCTION dbo.fn_GetChnNum; END; GO CREATE FUNCTI ...
 - input-file类型accept 属性对性能的影响
			
上传图片的时候,有时会加一些限制,如下,进行上传类型的过滤,如 <input type="file" name="pic" id="pic&qu ...