分析

三倍经验题,本文以[BZOJ1478][SGU282]Isomorphism为例展开叙述,主体思路与另外两题大(wan)致(quan)相(yi)同(zhi)。

这可能是博主目前写过最长也是最认真的题解了。

题目中规定“若两个已染色的图,其中一个图可以通过结点重新编号而与另一个图完全相同, 就称这两个染色方案相同”,说明这个置换群是定义在点上的,而染色方案是定义在边上的。把边的染色方案转化为点的染色方案不太现实,所以说我们可以考虑如何将点的置换转化为边的置换。

一个显然的结论是点的置换和边的置换是一一对应的,但是我们不能暴力枚举所有的点的置换,因为可以想到点的置换又可以和\(1 \sim n\)的排列一一对应,推出共有\(n!\)个点的置换。换一个角度考虑,一个点的置换是由多个循环节组成的,所以我们可以暴力枚举每个循环节的长度,直接由此转化为边的置换,计算出此时的边的置换的循环节个数后乘一个满足这种循环节长度组合的点的置换的个数,这样的复杂度是可以接受的。

假设我们枚举到这样一个数组\(cnt\),\(cnt[i]\)表示在这种点的置换中循环节长度为\(i\)的循环节有\(cnt[i]\)个。

考虑一个长度为\(l\)的点的置换的循环节,现在有两个结点都在这个循环节上,这样的两个结点会形成\(\lfloor \frac{l}{2} \rfloor\)个边的置换的循环节。

为什么?

  1. 1----6 考虑这样一个点的置换的循环节(1,2,3,4,5,6)(逆时针),
  2. / \ 会形成6/2=3个边的置换的循环节,分别为:
  3. / \ ((1,2),(2,3),(3,4),(4,5),(5,6),(6,1))
  4. 2 5 ((1,3),(2,4),(3,5),(4,6),(5,1),(6,2))
  5. \ / ((1,4),(2,5),(3,6))
  6. \ / 由于边是无向边,以上便是全部的3个边的置换的循环节。
  7. 3----4 点的置换的循环节长度为奇数时情况稍有不同。

如果两个结点中有一个在另一个长度为\(l'\)的循环节上,那么这样的两个结点会形成\(\frac{l \times l'}{lcm(l,l')}=gcd(l,l')\)个边的置换的循环节。

把所有以上两种边的置换的循环节的个数加起来就好了。

以上,我们已经得到了此时的边的置换的循环节个数,接下来我们想求出满足这种循环节长度组合的点的置换的个数。(又开始啰嗦了)

假设我们有一个\(1 \sim n\)的排列(注意这里要和前文所提到的“点的置换可以和\(1 \sim n\)的排列一一对应”进行区分,它们不一样!),可以从左到右在这个排列中截出\(cnt[1]\)个\(1\),\(cnt[2]\)个\(2\),......,以此类推。每一段截出来的数字我们可以认为这是一个点的置换的循环节。我们知道长度\(1 \sim n\)的排列有\(n!\)个,又注意到循环节关心的是每个数字的下一个是什么,而不关心第几个数字是什么,所以要排列数要除以\(\prod i^{cnt[i]}\)。又双注意到对于长度相同的几个循环节,我们其实不会区分它们,更不会考虑它们的先后顺序,所以又要除以\(\prod (cnt[i]!)\)。综上所述,满足这种循环节长度组合的点的置换的个数为:

\[\frac{n!}{(\prod i^{cnt[i]})(\prod (cnt[i]!))}
\]

根据Polya定理,把求出来的两坨东西搞一搞,最后乘一个\((n!)^{-1}\)即可。

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <cctype>
  7. #include <algorithm>
  8. #define rin(i,a,b) for(int i=(a);i<=(b);i++)
  9. #define rec(i,a,b) for(int i=(a);i>=(b);i--)
  10. #define trav(i,x) for(int i=head[(x)];i;i=e[i].nxt)
  11. using std::cin;
  12. using std::cout;
  13. using std::endl;
  14. typedef long long LL;
  15. const int MAXN=55;
  16. const int MAXM=1005;
  17. int n,m;LL MOD,ans=0;
  18. int cnt[MAXN];
  19. LL fac[MAXN];
  20. inline LL gcd(LL x,LL y){
  21. if(!x||!y) return x+y;
  22. while(y){
  23. std::swap(x,y);
  24. y%=x;
  25. }
  26. return x;
  27. }
  28. inline LL qpow(LL x,LL y){
  29. LL ret=1,tt=x%MOD;
  30. while(y){
  31. if(y&1) ret=ret*tt%MOD;
  32. tt=tt*tt%MOD;
  33. y>>=1;
  34. }
  35. return ret;
  36. }
  37. void dfs(int rem,int now){
  38. if(!rem){
  39. LL temp=0,mot=1;
  40. rin(i,1,now-1){
  41. if(!cnt[i]) continue;
  42. temp+=i/2*cnt[i];
  43. temp+=i*cnt[i]*(cnt[i]-1)/2;
  44. rin(j,i+1,now-1){
  45. if(!cnt[j]) continue;
  46. temp+=cnt[i]*cnt[j]*gcd(i,j);
  47. }
  48. }
  49. rin(i,1,now-1){
  50. if(!cnt[i]) continue;
  51. mot=mot*qpow(i,cnt[i])%MOD*fac[cnt[i]]%MOD;
  52. }
  53. ans=(ans+qpow(m,temp)*fac[n]%MOD*qpow(mot,MOD-2))%MOD;
  54. return;
  55. }
  56. if(now>rem) return;
  57. for(int i=0;i*now<=rem;i++){
  58. cnt[now]=i;
  59. dfs(rem-i*now,now+1);
  60. }
  61. }
  62. int main(){
  63. scanf("%d%d%lld",&n,&m,&MOD);
  64. fac[0]=1;
  65. rin(i,1,n) fac[i]=fac[i-1]*i%MOD;
  66. dfs(n,1);
  67. printf("%lld\n",ans*qpow(fac[n],MOD-2)%MOD);
  68. return 0;
  69. }

[BZOJ1478&1488&1815][SGU282]Isomorphism:Polya定理的更多相关文章

  1. 【BZOJ1478】Sgu282 Isomorphism Pólya定理神题

    [BZOJ1478]Sgu282 Isomorphism 题意:用$m$种颜色去染一张$n$个点的完全图,如果一个图可以通过节点重新标号变成另外一个图,则称这两个图是相同的.问不同的染色方案数.答案对 ...

  2. bzoj 1488: [HNOI2009]图的同构【polya定理+dfs】

    把连边和不连边看成黑白染色,然后就变成了 https://www.cnblogs.com/lokiii/p/10055629.html 这篇讲得好!https://blog.csdn.net/wzq_ ...

  3. BZOJ1478 Sgu282 Isomorphism

    Problem A: Sgu282 Isomorphism Time Limit: 15 Sec  Memory Limit: 64 MBSubmit: 172  Solved: 88[Submit] ...

  4. BZOJ 1815: [Shoi2006]color 有色图(Polya定理)

    题意 如果一张无向完全图(完全图就是任意两个不同的顶点之间有且仅有一条边相连)的每条边都被染成了一种颜色,我们就称这种图为有色图. 如果两张有色图有相同数量的顶点,而且经过某种顶点编号的重排,能够使得 ...

  5. bzoj1478:Sgu282 Isomorphism

    思路:由于题目中是通过改变点的编号来判断两种染色方案是否相同,而染色的确是边,于是考虑如何将点置换转化为边置换. 对于一个有n个点的完全图,其点置换有n!个(即全排列个数),又由于每一个边置换都对应了 ...

  6. 「算法笔记」Polya 定理

    一.前置概念 接下来的这些定义摘自 置换群 - OI Wiki. 1. 群 若集合 \(s\neq \varnothing\) 和 \(S\) 上的运算 \(\cdot\) 构成的代数结构 \((S, ...

  7. 【BZOJ 1478】 1478: Sgu282 Isomorphism (置换、burnside引理)

    1478: Sgu282 Isomorphism Description 给 定一个N 个结点的无向完全图( 任意两个结点之间有一条边), 现在你可以用 M 种颜色对这个图的每条边进行染色,每条边必须 ...

  8. 【转】Polya定理

    转自:http://endlesscount.blog.163.com/blog/static/82119787201221324524202/ Polya定理 首先记Sn为有前n个正整数组成的集合, ...

  9. 【群论】polya定理

    对Polya定理的个人认识     我们先来看一道经典题目:     He's Circles(SGU 294)         有一个长度为N的环,上面写着“X”和“E”,问本质不同的环有多少个(不 ...

随机推荐

  1. 图解 SQL 里的各种 JOIN

    约定 下文将使用两个数据库表 Table_A 和 Table_B 来进行示例讲解,其结构与数据分别如下: mysql> SELECT * FROM Table_A ORDER BY PK ASC ...

  2. 将python 2.6 升级到 2.7,及pip安装

    由于CentOS6.5 自带python版本为2.6.6,实际中使用的大多为2.7.x版本.于是手动升级. 查看python的版本 #python -VPython 2.6.6 1.下载Python- ...

  3. 多线程15-ReaderWriterLockSlim

        ));         }         );                     rwl.EnterUpgradeableReadLock();                     ...

  4. Spring Boot 2.2.0 正式发布,支持 JDK 13!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 推荐阅读: Spring Boot 2.2.0 正式发布了,可从 repo.spring.io 或是 Maven Centr ...

  5. Vue:Elementui中的Tag与页面其它元素相互交互的两三事

    前言 公司系统在用elementui做后台开发,不免遇到一些需要自己去根据原有的功能上,加一些交互的功能.今天来介绍下我在用elementUi里的Tag标签与多选框交互的过程,东西听上去很简单,但就是 ...

  6. w3c之js学习总结

    ①JavaScript:改变 HTML 内容 <p id="demo">JavaScript 能改变 HTML 元素的内容.</p> <script& ...

  7. java的idea项目文件夹合并,怎么分开

    一,如下图所示 二,只需要将这个去掉

  8. Chrome开发者工具详解(三)之浏览器调试完后如何清除所有的断点

  9. vscode学习(三)之如何修改打开终端的默认shell

    实现 第一步:打开VSCode的设置(Preferences>User Settings) 第二步:搜索terminal.integrated.shell.osx 的 并把它的值改为你的zsh安 ...

  10. 基于Nginx+nginx-rtmp-module+ffmpeg搭建rtmp、hls流媒体服务器(二)

    前言 Nginx-rtmp-module插件针对RTMP协议中一些命令,实现了事件通知和exec外部脚本处理.这里我通过一个简单的SpringBoot项目和Python代码,快速搭建一个HTTP服务来 ...