BZOJ1004[HNOI2008]Cards——polya定理+背包
题目描述
小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有
多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方
案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.
两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗
成另一种.Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).
输入
第一行输入 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种洗牌法中的一种代
替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。
输出
不同染法除以P的余数
样例输入
2 3 1
3 1 2
样例输出
提示
有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次 可得BRG
和GRB。
100%数据满足 Max{Sr,Sb,Sg}<=20。
我们知道$polya$定理是不动点方案$=\frac{1}{|G|}\sum\limits_{f\in G}^{ }m^{c(f)}$,其中$f$代表一种置换,而$c(f)$则代表在置换$f$下的循环数。因为在一种置换中同一循环的元素的颜色必须相同,所以每种置换的染色方案数为$m^{c(f)}$,而本题限制了每种颜色的染色数量所以不能直接套用公式。对于每种置换,假设其中有一个大小为$k$的循环,那么可以将它看做是一个大小为$k$的物品。那么我们要求的就是有若干个物品,要求将他们染色并使染成每种颜色的物品总大小分别为$Sr,Sg,Sb$,直接做一遍多维背包即可求出方案数。最后不要忘记不洗牌也是一种置换。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int a,b,c,m,p;
int n;
int v[100];
int f[30][30][30];
int vis[100];
int cnt;
int q[100];
ll ans;
ll quick(int x,int y)
{
ll res=1ll;
while(y)
{
if(y&1)
{
res=res*x%p;
}
y>>=1;
x=1ll*x*x%p;
}
return res;
}
int solve()
{
memset(q,0,sizeof(q));
memset(f,0,sizeof(f));
memset(vis,0,sizeof(vis));
cnt=0;
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
int sum=0;
int now=i;
while(!vis[now])
{
sum++;
vis[now]=1;
now=v[now];
}
q[++cnt]=sum;
}
}
f[0][0][0]=1;
for(int s=1;s<=cnt;s++)
{
int x=q[s];
for(int i=a;i>=0;i--)
{
for(int j=b;j>=0;j--)
{
for(int k=c;k>=0;k--)
{
if(i>=x)
{
f[i][j][k]+=f[i-x][j][k];
f[i][j][k]%=p;
}
if(j>=x)
{
f[i][j][k]+=f[i][j-x][k];
f[i][j][k]%=p;
}
if(k>=x)
{
f[i][j][k]+=f[i][j][k-x];
f[i][j][k]%=p;
}
}
}
}
}
return f[a][b][c];
}
int main()
{
scanf("%d%d%d%d%d",&a,&b,&c,&m,&p);
n=a+b+c;
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
}
ans+=solve();
ans%=p;
}
for(int i=1;i<=n;i++)
{
v[i]=i;
}
ans+=solve();
ans%=p;
ans*=quick(m+1,p-2);
ans%=p;
printf("%lld",ans);
}
BZOJ1004[HNOI2008]Cards——polya定理+背包的更多相关文章
- [BZOJ1004] [HNOI2008] Cards (Polya定理)
Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...
- bzoj1004 [HNOI2008]Cards Burnside定理+背包
题目传送门 思路:首先是Burnside引理,要先学会这个博客. Burnside引理我们总结一下,就是 每种置换下不动点的数量之和除以置换的总数,得到染色方案的数量. 这道题,显然每种 ...
- BZOJ1004 HNOI2008 Cards Burnside、背包
传送门 在没做这道题之前天真的我以为\(Polya\)可以完全替代\(Burnside\) 考虑\(Burnside\)引理,它要求的是对于置换群中的每一种置换的不动点的数量. 既然是不动点,那么对于 ...
- BZOJ1004: [HNOI2008]Cards(Burnside引理 背包dp)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4255 Solved: 2582[Submit][Status][Discuss] Descript ...
- BZOJ1004 [HNOI2008]Cards(Polya计数)
枚举每个置换,求在每个置换下着色不变的方法数,先求出每个循环的大小,再动态规划求得使用给定的颜色时对应的方法数. dp[i][j][k]表示处理到当前圈时R,B,G使用量为i,j,k时的方法数,背包思 ...
- bzoj1004 [HNOI2008]Cards Burnside 引理+背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1004 题解 直接 Burnside 引理就可以了. 要计算不动点的个数,那么对于一个长度为 \ ...
- bzoj1004 [HNOI2008]Cards 置换群+背包
[bzoj1004][HNOI2008]Cards 2014年5月26日5,3502 Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿 ...
- 【bzoj1004】[HNOI2008]Cards Burnside引理+背包dp
题目描述 用三种颜色染一个长度为 $n=Sr+Sb+Sg$ 序列,要求三种颜色分别有 $Sr,Sb,Sg$ 个.给出 $m$ 个置换,保证这 $m$ 个置换和置换 ${1,2,3,...,n\choo ...
- [BZOJ1004] [HNOI2008]Cards解题报告(Burnside引理)
Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...
随机推荐
- MyBatis-你所不了解的sql和include
目录 <sql> 节点的基础 <include> 节点 <sql> 节点包含的节点 一起来学习 mybatis @ 在前一篇[MyBatis动态SQL(认真看看, ...
- 论学习IT的基本学习方法
学习还是要通过实践总结这种方式去不断进步,当然这个思想对于生活中的任何事都是相通的,就像我现在做的就是总结一下自己的学习方法,更多的是针对于IT代码这块知识的总结. 我想通过这种博客总结的方式来不断总 ...
- linux 下mysql服务的管理
一.mysql服务的管理 1.1 mysql启动与关闭 linux下启动mysql: /etc/init.d/mysqld start 关闭进程: ps -ef | grep mysql 找到进程号 ...
- java中的代码块是什么意思,怎么用
代码块是一种常见的代码形式.他用大括号“{}”将多行代码封装在一起,形成一个独立的代码区,这就构成了代码块.代码块的格式如下: 方法/步骤 普通代码块:是最常见的代码块,在方法里用一对“{ ...
- Vue-router路由使用,单页面的实现
1.安装路由系统 NPM npm install vue-router 2.在main.js中进入引用 import VueRouter from 'vue-router' 3.创建三个空的组件: V ...
- 【转】shell之for、while、until循环
一.简介 Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种常用的循环语句:for.while和until.while循环和for循环属于“当型循环”,而unti ...
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-25: ordinal not in range(128)
python报错:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-25: ordinal not in ...
- PAT L2-020 功夫传人
https://pintia.cn/problem-sets/994805046380707840/problems/994805059118809088 一门武功能否传承久远并被发扬光大,是要看缘分 ...
- StackWalk64
#include <Windows.h> #define PULONG_PTR ULONG** #define PULONG ULONG* #define ULONG_PTR U ...
- <转>Python中的新式/经典类的查找方式
在学习到深度和广度的时候,懵了很久.后来看到这篇文章,恍然大悟.写的很好.特意转过来. 经典类: 只要有父类, 就会沿着一直找, 即使已经找过了~ 新式类: 在类继承的多个类拥有共同父类的情况下, 会 ...