【ybt金牌导航8-5-6】【luogu P1446】卡牌染色 / Cards(Burnside引理)(背包)

卡牌染色 / Cards

题目链接:ybt金牌导航8-5-6 / luogu P1446

题目大意

有 n 张牌,分别由三个颜色组成,每个颜色告诉你个数。
然后还会告诉你一些允许的置换方案,保证若干次置换都可以被其中的一个置换代替。
然后问你有多少种本质不同的排法,两种本质相同时可以通过置换把它们变成一样的。

思路

看到置换,然后颜色,考虑用 Polya 定理。
然而你发现颜色不是随便选,但是由于颜色很少,我们考虑用 Burnside 引理。

那显然根据题目置换的特殊条件,所有的置换就是它给出的加上不变的置换。(当然要处理给出的置换就有不变的置换的情况)
那显然我们可以直接找到每个循环,然后每个循环里面的的点都要同一个颜色。

然后你发现直接背包复杂度过得去,然后背包搞即可。
fi,j,k 为三个颜色选的个数分别为 i,j,k 的方案数,然后每次会放入一个当前循环大小的在三个颜色的其中一个转移即可。

代码

#include<cstdio> #include<cstring> #include<iostream> using namespace std; int sr, sb, sg, m, mo, n, f[21][21][21]; int a[101], in[101], num, l[101]; int ans, inv[101]; int ksm(int x, int y) { int re = 1; while (y) { if (y & 1) re = re * x % mo; x = x * x % mo; y >>= 1; } return re; } void work(int num) { memset(f, 0, sizeof(f)); f[0][0][0] = 1; for (int i = 1; i <= num; i++) {//背包 for (int x = sr; x >= 0; x--) for (int y = sb; y >= 0; y--) for (int z = sg; z >= 0; z--) { if (!f[x][y][z]) continue; if (x + l[i] <= sr) f[x + l[i]][y][z] = (f[x + l[i]][y][z] + f[x][y][z]) % mo; if (y + l[i] <= sb) f[x][y + l[i]][z] = (f[x][y + l[i]][z] + f[x][y][z]) % mo; if (z + l[i] <= sg) f[x][y][z + l[i]] = (f[x][y][z + l[i]] + f[x][y][z]) % mo; } } ans = (ans + f[sr][sb][sg]) % mo; } bool cksame() { for (int i = 1; i <= n; i++) if (a[i] != i) return 0; return 1; } int main() { scanf("%d %d %d %d %d", &sr, &sb, &sg, &m, &mo); n = sr + sb + sg; for (int j = 1; j <= n; j++) a[j] = j;//记得有不动这个置换 num = n; for (int i = 1; i <= n; i++) l[i] = 1; work(num); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) scanf("%d", &a[j]); if (cksame()) {//然后不动的置换也可能给出,要忽略掉 i--; m--;//同时总的置换数要减一 continue; } num = 0; for (int j = 1; j <= n; j++) if (in[j] != i) { num++; int now = a[j]; l[num] = 1; in[j] = i; while (now != j) { l[num]++; in[now] = i; now = a[now]; } } work(num); } ans = ans * ksm(m + 1, mo - 2) % mo;//记得加上不动的置换(如果重复在前面减去了) printf("%d", ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/YBT_JPDH_8-5-6.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(23)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示