bzoj1004 Cards
Posted GFY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1004 Cards相关的知识,希望对你有一定的参考价值。
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种洗牌法中的一种代替,且对每种
洗牌法,都存在一种洗牌法使得能回到原状态。
100%数据满足 Max{Sr,Sb,Sg}<=20。
Output
不同染法除以P的余数
Sample Input
1 1 1 2 7
2 3 1
3 1 2
2 3 1
3 1 2
Sample Output
2
根据burnside引理,我们可以知道,L=(1/G)*Σd(gi)
根据polay计数,可以转变为L=(1/G)*(每个置换里面的不变染色方案数)
但是这题三种颜色都有数量限制,因此,我们用dp运算每个置换里面不变的染色方案数。
还有一点,就是每个位置i上都放i也是一种置换,不要忘记加上这个置换的答案
最后乘以(m+1)在p下逆元即是答案。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int f[25][25][25]; 7 int n,b[105],st[105],id[105],sum[105],inv[205],m,p,sr,sb,sg,sz,g[205]; 8 int dp(){ 9 sz=0; 10 for (int i=1;i<=n;i++) b[i]=0; 11 for (int i=0;i<=n;i++) st[i]=id[i]=sum[i]=0; 12 sum[0]=0; 13 for (int i=1;i<=n;i++) 14 if (!b[i]){ 15 int ans=0; 16 while (!b[g[i]]) i=g[i],b[i]=1,ans++; 17 st[++sz]=ans;sum[sz]=sum[sz-1]+ans;id[sum[sz]]=sz; 18 } 19 for (int i=0;i<=sr;i++) 20 for (int j=0;j<=sb;j++) 21 for (int k=0;k<=sg;k++) 22 f[i][j][k]=0; 23 f[0][0][0]=1; 24 for (int i=0;i<=sr;i++) 25 for (int j=0;j<=sb;j++) 26 for (int k=0;k<=sg;k++) 27 if (id[i+j+k]){ 28 int v=st[id[i+j+k]]; 29 if (i>=v) f[i][j][k]=(f[i][j][k]+f[i-v][j][k])%p; 30 if (j>=v) f[i][j][k]=(f[i][j][k]+f[i][j-v][k])%p; 31 if (k>=v) f[i][j][k]=(f[i][j][k]+f[i][j][k-v])%p; 32 } 33 return f[sr][sb][sg]; 34 } 35 int main(){ 36 scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&p); 37 n=sr+sb+sg; 38 inv[1]=1; 39 int ans=0; 40 for (int i=2;i<p;i++) 41 inv[i]=(((p-p/i)%p)*(inv[p%i]))%p; 42 inv[p]=1; 43 for (int i=1;i<=m;i++){ 44 for (int j=1;j<=n;j++) 45 scanf("%d",&g[j]); 46 ans=(ans+dp())%p; 47 } 48 for (int i=1;i<=n;i++) 49 g[i]=i; 50 ans=(ans+dp())%p; 51 ans=(ans*inv[m+1])%p; 52 printf("%d\n",ans); 53 }
以上是关于bzoj1004 Cards的主要内容,如果未能解决你的问题,请参考以下文章