bzoj1004 [HNOI2008]Cards Burnside 引理+背包
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=1004
题解
直接 Burnside 引理就可以了。
要计算不动点的个数,那么对于一个长度为 \(x\) 的循环,必须全部是红色、蓝色、绿色三种。
所以显然可以 DP。令 \(dp[i][j][k]\) 表示前 \(i\) 个循环,\(j\) 张牌选了红色,\(k\) 张牌选了蓝色,剩下的选了绿色的方案数。背包转移就可以了。
最后记得要比 \(m\) 个置换多算一个 \(f_i = i\) 的排列,也就是不动的情况。
代码如下,时间复杂度 \(O(mn^3)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 60 + 7;
int n, nr, nb, ng, m, P;
int fa[N], sz[N], siz[N], s[N], dp[N][N][N];
inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
inline void merge(int x, int y) {
x = find(x), y = find(y);
if (x == y) return;
if (sz[x] < sz[y]) std::swap(x, y);
fa[y] = x, smax(sz[x], sz[y] + 1), siz[x] += siz[y];
}
inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
int ans = 1;
for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
return ans;
}
inline int DP() {
memset(dp, 0, sizeof(dp));
dp[0][0][0] = 1;
int i = 0;
for (int g = 1; g <= n; ++g) {
if (find(g) != g) continue;
++i;
s[i] = s[i - 1] + siz[g];
// dbg("***** i = %d\n", i);
for (int j = 0; j <= std::min(s[i], nr); ++j)
for (int k = 0; j + k <= s[i] && k <= nb; ++k)
if (s[i] - j - k <= ng) {
if (j >= siz[g]) sadd(dp[i][j][k], dp[i - 1][j - siz[g]][k]);
if (k >= siz[g]) sadd(dp[i][j][k], dp[i - 1][j][k - siz[g]]);
if (s[i] - j - k >= siz[g]) sadd(dp[i][j][k], dp[i - 1][j][k]);
// dbg("dp[%d][%d][%d] = %d, siz[g] = %d\n", i, j, k, dp[i][j][k], siz[g]);
}
}
return dp[i][nr][nb];
}
inline void work() {
for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = siz[i] = 1;
int ans = DP();
for (int k = 1; k <= m; ++k) {
for (int i = 1, x; i <= n; ++i) read(x), merge(i, x);
sadd(ans, DP());
}
ans = (ll)ans * fpow(m + 1, P - 2) % P;
printf("%d\n", ans);
}
inline void init() {
read(nr), read(nb), read(ng);
n = nr + nb + ng;
read(m), read(P);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
bzoj1004 [HNOI2008]Cards Burnside 引理+背包的更多相关文章
- BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4255 Solved: 2582[Submit][Status][Discuss] Descript ...
- 【bzoj1004】[HNOI2008]Cards Burnside引理+背包dp
题目描述 用三种颜色染一个长度为 $n=Sr+Sb+Sg$ 序列,要求三种颜色分别有 $Sr,Sb,Sg$ 个.给出 $m$ 个置换,保证这 $m$ 个置换和置换 ${1,2,3,...,n\choo ...
- BZOJ1004 HNOI2008 Cards Burnside、背包
传送门 在没做这道题之前天真的我以为\(Polya\)可以完全替代\(Burnside\) 考虑\(Burnside\)引理,它要求的是对于置换群中的每一种置换的不动点的数量. 既然是不动点,那么对于 ...
- bzoj1004: [HNOI2008]Cards(burnside引理+DP)
题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染 ...
- bzoj1004 [HNOI2008]Cards Burnside定理+背包
题目传送门 思路:首先是Burnside引理,要先学会这个博客. Burnside引理我们总结一下,就是 每种置换下不动点的数量之和除以置换的总数,得到染色方案的数量. 这道题,显然每种 ...
- 【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( ...
- BZOJ 1004 HNOI2008 Cards Burnside引理
标题效果:特定n张卡m换人,编号寻求等价类 数据保证这m换人加上置换群置换后本身构成 BZOJ坑爹0.0 条件不那么重要出来尼玛怎么做 Burnside引理--昨晚为了做这题硬啃了一晚上白书0.0 都 ...
- BZOJ1004[HNOI2008]Cards——polya定理+背包
题目描述 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色 ...
随机推荐
- vue中的render函数介绍
简介:对于不了解slot的用法(参考:大白话vue-slot的用法)又刚接触render函数的同学来说,官网的解释无疑一脸懵逼,这里就整理下个人对render函数的理解 问题: 1.render函数是 ...
- luoguP4721 【模板】分治 FFT (分治NTT)
给定 $g[1....n-1]$,求 $f[0],f[1],...,f[n-1]$,其中 $f[i]=\sum_{j=1}^{i}f[i-j]g[j]$ 变界为 $f[0]=1$ 答案模 9 ...
- luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- [java] [error] java.lang.OutOfMemoryError: unable to create new native thread
前言 最近公司的服务器出现了oom的报错,经过一番排查,终于找到了原因.写下这篇博客是为了记录下查找的过程,也是为了帮助那些跟我门遇到的情况相同的人可以更快的寻找到答案. 环境 系统:linux(ce ...
- 2018-2019-2 20175307 实验四《Android程序设计》实验报告
任务一 实验要求和内容: Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十 ...
- VS code 同步设置与插件
准备工作:拥有一个github账户,电脑上需安装VSCode.实现同步的功能主要依赖于VSCode插件 "Settings Sync"第一步:安装同步插件Settings Sync ...
- 16/7/14-MySQL-遇到的基本问题
从一开始遇到的3534 ---------------------------------------------------------------------------------------- ...
- ADFS 2016 & Dynamics CRM
参考:https://blog.csdn.net/vic0228/article/details/80188291 webapp 获取token https://adfs.demo.local/adf ...
- poi3617Best Cow Line ——贪心法
给定长度为N(1≤N≤2000)的字符串S,要构造一个长度为N的字符串T.期初,T是一个空串,随后反复进行下列任意操作. ·从S的头部删除一个字符,加到T的尾部 ·从S的尾部删除一个字符,加到T的尾部 ...
- Naive Bayes Algorithm And Laplace Smoothing
朴素贝叶斯算法(Naive Bayes)适用于在Training Set中,输入X和输出Y都是离散型的情况.如果输入X为连续,输出Y为离散,我们考虑使用逻辑回归(Logistic Regression ...