题目链接

(Luogu) https://www.luogu.org/problem/P4727
(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=1488

题解

Burnside引理经典题。

首先考虑一个\(O(n!\times poly(n))\)暴力: 枚举点的置换,然后计算在置换下保持不变的图的个数。
把置换拆成若干个轮换。
(1) 考虑轮换内部: 假设一轮换为\((a_1\ a_2\ ...\ a_n)\), 那么\((a_1,a_2),(a_2,a_3),...,(a_n,a_1)\)这些边要么都存在要么都不存在;\((a_1,a_3),(a_2,a_4),...,(a_{n-1},a_{1}),(a_{n},a_2)\)这些边也要么都存在要么都不存在;一般地说,对于任何一个\(d\), 所有的\((a_i,a_{(i+d)\mod n})\)这些边要么都存在要么都不存在,因此轮换内部一共有\(2^{\frac{n}{2}}\)种方案。
(2) 考虑轮换之间: 假设两轮换分别为\((a_1,a_2,...,a_n),(b_1,b_2,...,b_m)\)则有: \((a_1,b_1),(a_2,b_2),...(a_i,b_i)\)这些边存在情况都相同;\((a_1,b_2),(a_2,b_3),...,(a_i,b_{i+1})\)这些边存在情况都相同;以此类推,可以得到两轮换之间共有\(2^{\gcd(n,m)}\)种方案。
所有的置换方案数相加,最后除以置换总数\(n!\).

然后现在考虑\(n\le 60\)怎么办。
当\(n\le 60\)时,我们可以枚举拆分数(\(60\)的拆分数约为百万级别)。
已知一个拆分的方案(方案是指一个无标号序列\(a\)满足\(\sum a_i=n\),其长度为\(cnt\)),它对应了多少个不同排列的轮换分拆?
首先,长度为\(L\)的轮换共\((L-1)!\)种。
然后我们要处理标号问题。
假设轮换之间是有区别的,那么标号方案数为\(\frac{n!}{\prod^{cnt}_{i=1}a_i!}\).
但是长度相等的轮换之间没有区别,所以除以\(\prod {num_i!}\), 其中\(num_i\)表示\(i\)在\(a\)中的出现次数。
最后乘起来得到\(\frac{n!}{\prod^{cnt}_{i=1}a_i\prod^n_{i=1}num_i!}\)
累加即可。

时间复杂度?
枚举所有拆分方案,求\(cnt^2\)之和,我用程序计算得当\(n=60\)时该值约为\(2.7\times 10^8\).

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#define llong long long
using namespace std;inline int read()
{int x=0; bool f=1; char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=0;for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');if(f) return x;return -x;
}const int N = 60;
const int P = 997;
llong fact[N+3],finv[N+3],inv[N+3];
llong pw2[N+3];
int a[N+3];
int num[N+3];
int gcd[N+3][N+3];
int n,cnt;
llong ans;int GCD(int x,int y)
{return y==0?x:GCD(y,x%y);
}llong quickpow(llong x,llong y)
{llong cur = x,ret = 1ll;for(int i=0; y; i++){if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}cur = cur*cur%P;}return ret;
}llong calc()
{llong ret = fact[n];for(int i=1; i<=cnt; i++){ret = ret*inv[a[i]]%P;}for(int i=1; i<=n; i++){ret = ret*finv[num[i]]%P;}for(int i=1; i<=cnt; i++){ret = ret*pw2[a[i]>>1]%P;}for(int i=1; i<=cnt; i++){for(int j=i+1; j<=cnt; j++){ret = ret*pw2[gcd[a[i]][a[j]]]%P;}}return ret;
}void dfs(int sum)
{if(sum==n){ans = (ans+calc())%P;return;}for(int i=a[cnt]; i+sum<=n; i++){cnt++; a[cnt] = i; num[i]++;dfs(i+sum);a[cnt] = 0; cnt--; num[i]--;}
}int main()
{pw2[0] = 1ll; for(int i=1; i<=N; i++) pw2[i] = (pw2[i-1]<<1)%P;fact[0] = 1ll; for(int i=1; i<=N; i++) fact[i] = fact[i-1]*i%P;finv[N] = quickpow(fact[N],P-2); for(int i=N-1; i>=0; i--) finv[i] = finv[i+1]*(i+1)%P;for(int i=1; i<=N; i++) inv[i] = finv[i]*fact[i-1]%P;for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) gcd[i][j] = GCD(i,j);scanf("%d",&n);if(n==0) {printf("1"); return 0;}a[0] = 1; dfs(0);ans = ans*finv[n]%P;printf("%lld\n",ans);return 0;
}

BZOJ 1488 Luogu P4727 [HNOI2009]图的同构 (Burnside引理、组合计数)相关推荐

  1. BZOJ 1488 Luogu P4727 [HNOI2009]图的同构 (群论、Burnside引理、组合计数)

    题目链接 (Luogu) https://www.luogu.org/problem/P4727 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.ph ...

  2. Luogu P5564 [Celeste-B]Say Goodbye (多项式、FFT、Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P5564 题解 这题最重要的一步是读明白题. 为了方便起见下面设环长可以是\(1\), 最后统计答案时去掉即可. 实际上就相当于 ...

  3. Luogu P4708 画画 (Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P4708 题解 看上去Luogu P4706-4709是Sdchr神仙出的一场比赛,一道水题和三道很有趣的题终于全过了纪念QAQ ...

  4. Luogu P4708 画画 (Burnside引理、组合计数、划分数)

    题目链接 https://www.luogu.org/problem/P4708 题解 看上去Luogu P4706-4709是Sdchr神仙出的一场比赛,一道水题和三道很有趣的题终于全过了纪念QAQ ...

  5. 置换群burnside引理(bzoj 1004: [HNOI2008]Cards)

    置换群: 看半天置换群表示并看不懂QAQ 但顾名思义是置换组成的群 其实不用看懂也行,就拿简单的例子来说吧 有一个序列s = {1, 2, 3, 4, 5, 6} 和一个变换规则t = {2, 3, ...

  6. 置换群,Polya引理和burnside引理(等价类计数问题)

    参考文章: 等价类计数问题 Burnside引理&Pólya定理 Burnside引理与Polya定理 置换群和Burnside引理,Polya定理 概念引入: 离散数学应该学过置换群的相关概 ...

  7. 置换群和Burnside引理,Polya定理

    定义简化版: 置换,就是一个1~n的排列,是一个1~n排列对1~n的映射 置换群,所有的置换的集合. 经常会遇到求本质不同的构造,如旋转不同构,翻转交换不同构等. 不动点:一个置换中,置换后和置换前没 ...

  8. 数学:Burnside引理与Pólya定理

    这个计数定理在考虑对称的计数中非常有用 先给出这个定理的描述,虽然看不太懂: 在一个置换群G={a1,a2,a3--ak}中,把每个置换都写成不相交循环的乘积. 设C1(ak)是在置换ak的作用下不动 ...

  9. Burnside引理与Pólya定理

    正文 hht主要讲了Burnside引理的不完全证明和用Burnside引理推出Pólya定理 下面主要围绕这两方面来讨论 Burnside引理的不完全证明 有一个前置结论hht没有证明,说是需要引入 ...

最新文章

  1. centos安装ssdb
  2. 大润发优鲜app之paramsMD5参数分析
  3. “报复黑客”:可行的战略还是重大的风险?
  4. .Net Core 认证系统之基于Identity Server4 Token的JwtToken认证源码解析
  5. 电力、市政、交通三大领域推动工业交换机行业发展
  6. jquery3和layui冲突导,致使用layui.layer.full弹出全屏iframe窗口时高度152px问题
  7. 阿里云环境中TLS/SSL握手失败的场景分析
  8. 案例解读:利用12c渐进式DASH分析ON CPU
  9. python识别验证码ocr_Python3使用tesserocr识别字母数字验证码
  10. 吐血推荐 | 5+1款源代码管理笔记本(全平台)
  11. Java 生成 验证码图片
  12. 联想笔记本windows10,点击蓝牙显示无法连接
  13. 色环电阻计算器_色环电感标示法_
  14. 谷歌关键字推广操作技巧
  15. Android将2张图片合成一张图片(Bitmap类型)附二维码生成
  16. 手机ping软件测试网速,网速测试 - wifi测网速,网络ping test
  17. 处理数据时,对数据取对数的意义
  18. 限定当天的可用次数 redis
  19. 数据库三大范式详解,部分依赖、完全依赖、传递依赖
  20. hydra暴力破解ssh密码

热门文章

  1. 云炬Android开发笔记 2-2 Android studio项目上传到Github及无法连接Github的问题处理
  2. sqlserver2008 安装时需要重启的解决办法
  3. 【CyberSecurityLearning 27】扫描与密码爆破
  4. 约束条件创建定义表(主码,外码的确定和防止空值等)
  5. eclipse忘记了程序保存在哪里怎么办
  6. 通过/proc/PID/status查看进程内存占用情况
  7. C语言再学习 -- vim常用快捷键(转)
  8. 以太坊Sharding FAQ
  9. All of Recurrent Neural Networks (RNN)
  10. 区块链应用于供应链金融的完整解决方案