[HNOI2008]Cards
2017-10-22 14:51
141 查看
题目描述
小春现在很清闲,面对书桌上的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种洗牌法中的一种代替,且对每种
洗牌法,都存在一种洗牌法使得能回到原状态。
100%数据满足 Max{Sr,Sb,Sg}<=20。
输出格式:
不同染法除以P的余数
输入输出样例
输入样例#1: 复制1 1 1 2 7 2 3 1 3 1 2
输出样例#1: 复制
2
说明
有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次 可得BRG 和GRB。[b]题目大意:给出n张牌,分别染a张红色,b张蓝色,c张绿色(n=a+b+c),给出m个置换,问不同的染色方案。[/b]
[b]红色部分就是告述你这些置换构成置换群[/b]
[b]置换群中的染色方案问题可用polya定理解决。[/b]
[b]只要满足同一循环染同一种色[/b]
[b]因为3种颜色要满足数量限制,不能用polya,但可以用burnside[/b]
[b]所以用三维背包求出在置换$a_j$下不变的元素个数$D(a_j)$[/b]
[b]还要算上不置换,也就是单位置换[/b]
[b]所以总共有$|G|=m+1$种置换,根据burnside引理[/b]
[b]$ans=\frac{1}{G}\sum_{j=1}^{m+1}D(a_j)$[/b]
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int sr,sb,sg,n,m,p,inv; int vis[1001],f[101][21][21][21],tot,A[1001],s[1001],ans; int qpow(int x,int y) { int res=1; while (y) { if (y&1) res=res*x%p; x=x*x%p; y/=2; } return res; } int dfs(int x,int cnt) { if (vis[x]) return cnt; vis[x]=1; return dfs(A[x],cnt+1); } int main() {int i,a,b,c; cin>>sr>>sb>>sg>>m>>p; n=sr+sb+sg; inv=qpow(m+1,p-2); while (m--) { tot=0; memset(vis,0,sizeof(vis)); for (i=1;i<=n;i++) scanf("%d",&A[i]); for (i=1;i<=n;i++) if (vis[i]==0) { s[++tot]=dfs(i,0); } memset(f,0,sizeof(f)); f[0][0][0][0]=1; for (i=1;i<=tot;i++) { for (a=0;a<=sr;a++) { for (b=0;b<=sb;b++) { for (c=0;c<=sg;c++) { if (a>=s[i]) { f[i][a][b][c]+=f[i-1][a-s[i]][b][c]; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } if (b>=s[i]) { f[i][a][b][c]+=f[i-1][a][b-s[i]][c],f[i][a][b][c]%=p; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } if (c>=s[i]) { f[i][a][b][c]+=f[i-1][a][b][c-s[i]]; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } } } } } ans+=f[tot][sr][sb][sg]; if (ans>=p) ans-=p; } memset(f,0,sizeof(f));f[0][0][0][0]=1; for (i=1;i<=n;i++) { for (a=0;a<=sr;a++) { for (b=0;b<=sb;b++) { for (c=0;c<=sg;c++) { if (a>=1) { f[i][a][b][c]+=f[i-1][a-1][b][c]; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } if (b>=1) { f[i][a][b][c]+=f[i-1][a][b-1][c],f[i][a][b][c]%=p; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } if (c>=1) { f[i][a][b][c]+=f[i-1][a][b][c-1]; if (f[i][a][b][c]>=p) f[i][a][b][c]-=p; } } } } } ans+=f [sr][sb][sg]; if (ans>=p) ans-=p; cout<<ans*inv%p; }
相关文章推荐
- [BZOJ1004][HNOI2008]Cards-Burnside引理
- bzoj [HNOI2008]Cards
- 【BZOJ】【P1004】【HNOI2008】【Cards】【题解】【Burnside引理+dp】
- [HNOI2008]Cards (polya定理+乘法逆元,费马小定理)
- P1446 [HNOI2008]Cards
- BZOJ1004 [HNOI2008]Cards 【burnside定理 + 01背包】
- bzoj 1004: [HNOI2008]Cards
- [Polya群论]BZOJ1004: [HNOI2008]Cards
- BZOJ1004:[HNOI2008]Cards (Burnside引理+DP+Exgcd)
- 【BZOJ1004】【HNOI2008】Cards
- [BZOJ1004][HNOI2008]Cards(Burnside引理+dp)
- bzoj1004 [HNOI2008]Cards(burnside引理+背包dp)
- BZOJ 1004 [HNOI2008] Cards
- BZOJ 1004 [HNOI2008]Cards
- BZOJ 1004([HNOI2008]Cards-Polya计数+k背包)
- bzoj 1004: [HNOI2008]Cards(置换)
- 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP
- 【bzoj 1004】 Cards 【HNOI2008】
- HYSBZ/BZOJ 1004 [HNOI2008] Cards - 组合数学
- [BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】