burnside引理
2016-05-04 18:46
429 查看
burnside引理:
对于置换群G,G的轨道数= ∑(G中每个置换的不动点个数)/|G|\sum(G中每个置换的不动点个数)/|G|
没错我也是来报社的,反正我只是打算自己总结一下
那么这个东西有什么用呢?有一类问题是这样的:有N个元素,M种颜色(或者每种颜色有使用次数限制),那么现在还有一个置换群,一种染色方案与它经过这些置换之后得到的方案视为等价,求不同的染色方案数。
首先不考虑在置换群下的等价,把每种染色方案视为一个元素,对于每个染色方案,经过一个置换以后都可以对应另一个染色方案(也可能不变)。那么对于每个置换我们又能得到以染色方案为元素的置换,考虑这些以方案为元素的置换构成的置换群,记为GG。根据轨道的定义(一个轨道内的元素经过置换群内的置换得到的都是同一轨道内的元素),我们要求的方案数正是GG的轨道数,那么就可以利用burnside引理求出轨道数即方案数了。
于是不动点怎么求?这个应该是因题而异的。我刚做的一道题的做法是:对于原来每个置换,使每个循环节内的元素都染上同一种颜色,再求这种情况下的方案数,那就得到这个置换在GG中对应的置换的不动点的个数了,因为很显然这些方案在这个置换下都不会发生改变。于是每个置换求一遍不动点个数再加起来就好啦。至于有没有其他方法就有待研究啦。
其实我刚做的题是BZOJ1004,还是贴一下代码吧→_→
对于置换群G,G的轨道数= ∑(G中每个置换的不动点个数)/|G|\sum(G中每个置换的不动点个数)/|G|
没错我也是来报社的,反正我只是打算自己总结一下
那么这个东西有什么用呢?有一类问题是这样的:有N个元素,M种颜色(或者每种颜色有使用次数限制),那么现在还有一个置换群,一种染色方案与它经过这些置换之后得到的方案视为等价,求不同的染色方案数。
首先不考虑在置换群下的等价,把每种染色方案视为一个元素,对于每个染色方案,经过一个置换以后都可以对应另一个染色方案(也可能不变)。那么对于每个置换我们又能得到以染色方案为元素的置换,考虑这些以方案为元素的置换构成的置换群,记为GG。根据轨道的定义(一个轨道内的元素经过置换群内的置换得到的都是同一轨道内的元素),我们要求的方案数正是GG的轨道数,那么就可以利用burnside引理求出轨道数即方案数了。
于是不动点怎么求?这个应该是因题而异的。我刚做的一道题的做法是:对于原来每个置换,使每个循环节内的元素都染上同一种颜色,再求这种情况下的方案数,那就得到这个置换在GG中对应的置换的不动点的个数了,因为很显然这些方案在这个置换下都不会发生改变。于是每个置换求一遍不动点个数再加起来就好啦。至于有没有其他方法就有待研究啦。
其实我刚做的题是BZOJ1004,还是贴一下代码吧→_→
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<iomanip> #include<vector> #include<set> #include<map> #include<queue> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define rep(i,k,n) for(int i=(k);i<=(n);i++) #define rep0(i,n) for(int i=0;i<(n);i++) #define red(i,k,n) for(int i=(k);i>=(n);i--) #define sqr(x) ((x)*(x)) #define clr(x,y) memset((x),(y),sizeof(x)) #define pb push_back int s[5],n,m,mod,cnt,ans,a[110],b[110],dp[25][25][25]; bool vis[110]; int quipow(int x,int k) { int ret=1; while(k) { if(k&1)ret=ret*x%mod; x=x*x%mod; k>>=1; } return ret; } inline void upd(int &x,int y) { x=(x+y)%mod; } int gao() { clr(dp,0); dp[0][0][0]=1; rep(i,1,cnt) { red(j,s[1],0)red(k,s[2],0)red(l,s[3],0) { if(j>=b[i])upd(dp[j][k][l],dp[j-b[i]][k][l]); if(k>=b[i])upd(dp[j][k][l],dp[j][k-b[i]][l]); if(l>=b[i])upd(dp[j][k][l],dp[j][k][l-b[i]]); } } return dp[s[1]][s[2]][s[3]]; } int main() { rep(i,1,3)scanf("%d",&s[i]); n=s[1]+s[2]+s[3]; scanf("%d%d",&m,&mod); cnt=n; rep(i,1,n)b[i]=1; ans=gao(); rep(i,1,m) { rep(j,1,n)scanf("%d",&a[j]); clr(vis,0); cnt=0; clr(b,0); rep(j,1,n)if(!vis[j]) { cnt++; int x=j; while(1) { vis[x]=1; b[cnt]++; if(vis[a[x]])break; x=a[x]; } } ans=(ans+gao())%mod; } printf("%d\n",ans*quipow(m+1,mod-2)%mod); return 0; }
相关文章推荐
- 分布式配置管理平台 Disconf
- android 利用左右滑动手势实现avtivity的跳转
- getdate.php var_dump($arry);
- 自组织特征映射SOM(Self-organizing feature Map)
- Spring @PostConstruct and @PreDestroy example
- Python-OpenCV 图像与视频处理
- 驱动编程-idt hook--中断描述符表
- grep、sed、awk
- NVIDIA JETSON 连接九轴IMU传感器(GY-85模块)
- Bagging, Boosting, and Randomization对比
- mysql主从复制的高可用解决方案
- Android学习记录(十二) http之base/digest鉴权。
- UESTC 482 Charitable Exchange(优先队列+bfs)
- UESTC 482 Charitable Exchange(优先队列+bfs)
- 为什么$(selector)之后,返回的是jQuery对象?
- js 数组与对象的区别
- python PIL图片处理模块实例
- 关于ubuntu内核升级的问题
- JavaScript在Unicode值和字符串中的字符间转换
- Python-OpenCV 杂项(二)(三): 鼠标事件、 程序性能的检测和优化