bzoj1004:[HNOI2008]Cards

思路:由于题目给出了置换,又要求本质不同的方案数,考虑使用Burnside引理,Burnside引理即通过所有置换和原来相同的方案数之和除以方案数总数,而对于某一个置换要使置换后得到的与原来的相同,就应该把置换形成的环染成同一种颜色,也就是说属于一个环内的元素颜色一定相同,然后有一定要有一定量的红蓝绿色,因此用一个完全背包去背即可,

f[i][j][k]表示选了i张红色j张蓝色k张绿色的方案数,f[i][j][k]=f[i][j][k]+f[i-sum][j][k]+f[i][j-sum][k]+f[i][j][k-sum](sum表示当前环大小,然后i,j,k一定要判是不是大于sum),最后还有就是任何时候都不要忘了不动也是一个置换,因此有m+1个置换。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 65
 8  
 9 int sr,sg,sb,m,p,n,ans,tot;
10 int a[maxn],next[maxn],vis[maxn],f[21][21][21],sum[maxn];
11 
12 int calc(){
13     for (int i=1;i<=n;i++) next[i]=a[i];tot=0,memset(vis,0,sizeof(vis)),memset(f,0,sizeof(f)),memset(sum,0,sizeof(sum));
14     for (int i=1;i<=n;i++) if (!vis[i]){
15         int size=0;
16         while (!vis[i]) vis[i]=1,size++,i=next[i];
17         sum[++tot]=size;
18     }
19     f[0][0][0]=1;
20     for (int i=1;i<=tot;i++)
21         for (int j=sr;j>=0;j--)
22             for (int k=sg;k>=0;k--)
23                 for (int l=sb;l>=0;l--){
24                     if (j>=sum[i]) f[j][k][l]=(f[j][k][l]+f[j-sum[i]][k][l])%p;
25                     if (k>=sum[i]) f[j][k][l]=(f[j][k][l]+f[j][k-sum[i]][l])%p;
26                     if (l>=sum[i]) f[j][k][l]=(f[j][k][l]+f[j][k][l-sum[i]])%p;
27                 }
28     return f[sr][sg][sb];
29 }
30 
31 int power(int a,int k,int p){
32     if (k==0) return 1;
33     if (k==1) return a%p;
34     int x=power(a,k/2,p),ans=x*x%p;
35     if (k&1) ans=ans*a%p;
36     return ans;
37 }
38 
39 int main(){
40     scanf("%d%d%d%d%d",&sr,&sg,&sb,&m,&p),n=sr+sg+sb;
41     for (int i=1;i<=n;i++) a[i]=i;ans=(ans+calc())%p;
42     for (int i=1;i<=m;i++){
43         for (int j=1;j<=n;j++)
44             scanf("%d",&a[j]);
45         ans=(ans+calc())%p;
46     }
47     ans=ans*power(m+1,p-2,p)%p;
48     printf("%d\n",ans);
49     return 0;
50 }
View Code

然后听说这道题有一个玄学写法,答案就是n!/(Sr!*Sg!*Sb!*(m+1)),然而蒟蒻并不知道这是为什么。。。。。神犇求教。。。

转载于:https://www.cnblogs.com/DUXT/p/5951580.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值