博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ1004][HNOI2008]Cards 群论+置换群+DP
阅读量:4708 次
发布时间:2019-06-10

本文共 2689 字,大约阅读时间需要 8 分钟。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1004

首先贴几个群论相关定义和引理。

 

群:G是一个集合,*是定义在这个集合上的一个运算。

如果满足以下性质,那么(G, *)是一个群。

1)封闭性,对于任意 a, b 属于 G, a * b 属于 G

2)结合律, a * b * c = a * (b * c)

3)单位元,在 G 中存在一个单位元 e ,使得对于 G 中任意的 a , a * e = e * a = a

4)逆元, 对于 G 中任意的 a ,在 G 中存在 b , 使得 a * b = e , 其中 b 叫做 a 的逆元

比如在模一个数意义下的整数加法就是一个群。

满足交换律的群是交换群,又叫阿贝尔群。

 

置换:可以用 (a1 -> b1, a2 -> b2, ... , an -> bn) 表示一个置换,其中 a1, ... , an 和 b1, ..., bn 都是1 到 n 的一个排列;

如果一些置换和它们的叠加运算构成一个群,就把它们叫做一个置换群。

 

在置换群中的 Burnside 引理:如果按照一定要求,要对1到n 的位置染色,那么本质不同的染色方案数为置换群中每个置换的不动染色方案数的平均数。

来解释以下,本质不同的染色方案是指,两个染色方案不能通过置换群中的任意置换变换使其相同,那么它们就是本质不同的。

某个置换的不动染色方案数是指,用这个置换变换之后没有发生变化的染色方案。

 

那么我们就是要求出每个置换的不动染色方案数。

Polya定理,如果是用k种颜色染色,那么对于置换 P 来说,它的不动染色方案数为 k^(L(P)), 其中L(P)为置换P的循环节数。

 

由于这道题中有颜色数目的限制,我们不能直接套Polya定理,但是可以把每个循环节当作一种物品,用背包求方案数。

1 #include
2 #include
3 #include
4 using namespace std; 5 int inline readint(){ 6 int Num;char ch; 7 while((ch=getchar())<'0'||ch>'9');Num=ch-'0'; 8 while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0'; 9 return Num;10 }11 int Sr,Sb,Sg,n,m,mod;12 int quick_pow(int x,int y){13 int base=x,sum=1;14 while(y){15 if(y&1) sum=sum*base%mod;16 base=base*base%mod;17 y>>=1;18 }19 return sum;20 }21 int fm[65][65],cnt[65],f[65/3][65/3][65/3];22 bool vis[65];23 int dp(int x){24 int tot=0;25 memset(vis,false,sizeof(vis));26 memset(cnt,0,sizeof(cnt));27 memset(f,0,sizeof(f));28 for(int i=1;i<=n;i++){29 if(!vis[i]){30 int j=i;31 tot++;32 while(!vis[fm[x][j]]){33 vis[fm[x][j]]=true;34 cnt[tot]++;35 j=fm[x][j];36 }37 }38 }39 f[0][0][0]=1;40 for(int i=1;i<=tot;i++)41 for(int j=Sr;j>=0;j--)42 for(int k=Sb;k>=0;k--)43 for(int t=Sg;t>=0;t--){44 if(j>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j-cnt[i]][k][t])%mod;45 if(k>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j][k-cnt[i]][t])%mod;46 if(t>=cnt[i]) f[j][k][t]=(f[j][k][t]+f[j][k][t-cnt[i]])%mod;47 }48 return f[Sr][Sb][Sg];49 }50 int main(){51 Sr=readint();52 Sb=readint();53 Sg=readint();54 m=readint();55 mod=readint();56 n=Sr+Sb+Sg;57 for(int i=1;i<=m;i++)58 for(int j=1;j<=n;j++)59 fm[i][j]=readint();60 m++;61 for(int i=1;i<=n;i++) fm[m][i]=i;62 int ans=0;63 for(int i=1;i<=m;i++) ans+=dp(i);64 ans=ans*quick_pow(m,mod-2)%mod;65 printf("%d\n",ans);66 return 0;67 }

 

转载于:https://www.cnblogs.com/halfrot/p/7481690.html

你可能感兴趣的文章
CSS选择器分类
查看>>
Kali学习笔记39:SQL手工注入(1)
查看>>
C# MD5加密
查看>>
Codeforces Round #329 (Div. 2)D LCA+并查集路径压缩
查看>>
移动应用开发测试工具Bugtags集成和使用教程
查看>>
Java GC、新生代、老年代
查看>>
Liferay 6.2 改造系列之十一:默认关闭CDN动态资源
查看>>
多线程
查看>>
折线切割平面
查看>>
获取当前路径下的所有文件路径 :listFiles
查看>>
图像形态学及更通用的形态学的原理及细节汇总
查看>>
linux开启coredump的3种方法
查看>>
数据驱动之 python + requests + Excel
查看>>
小鸡啄米问题求解
查看>>
Castle.net
查看>>
HDU1532 网络流最大流【EK算法】(模板题)
查看>>
PHP使用curl替代file_get_contents
查看>>
Webstorm通用设置
查看>>
jquery倾斜的动画导航菜单
查看>>
JAVA IO流的简单总结+收集日志异常信息
查看>>