题意与数据范围

求 \(n\) 个点不同构的简单无向图的数目,答案对 \(997\) 取模

\(A\) 图与 \(B\) 图被认为是同构的是指:\(A\) 图的顶点经过一定的重新标号以后,\(A\) 图的顶点集和边集要完全与 \(B\) 图一一对应

\(0\le n\le 60\)

Solution

我们把无向图点的每一种重新排布的方式看作一种置换,则该置换群 \(G\) 的大小显然为 \(n!\)

对于置换群 \(G\) 中的每一个置换 \(g\) ,在 \(g\) 的作用下的不动点即为这样的一种连边方案:
\[ \forall (a,b)\in (V,E),\exist (P_a,P_b)\in (V,E) \]
其中 \((a,b)\) 表示一条从 \(a\) 到 \(b\) 的无向边,\((V,E)\) 表示一张 \(V\) 个节点,\(E\) 条边的无向图,\(P_x\) 表示在置换 \(g\) 中编号为 \(x\) 的点所对应的置换

定义 \(X\) 为所有连边方案的集合,我们把在置换 \(g\) 下拥有上述性质的方案集合称为 \(X^g\) ,那么根据 \(\text{Burnside}\) 引理,答案即为 \(\frac{1}{|G|}\sum\limits_{g\in G}|X^g|\)

考虑如何计算 \(|X^g|\)

首先我们来考虑一下对于一个置换 \(g\) ,我们将它分解成若干个循环的乘积后,每一个循环内部的不动点如何计算

假设现在我们有一个循环 \(A\),其中第 \(i\) 个元素为 \(A_i\),假如 \(A_i\) 与 \(A_j\) 之间有一条边,那么所有下标“相距” \(|i-j|\) 的元素之间都必须有一条边,所以共有 \(\lfloor \frac{x}{2} \rfloor\) 种不同类型的边,对于同一种类型的边,我们要不都不连,要么都连,所以对于一个大小为 \(x\) 的循环,内部有 \(2^{\lfloor \frac{x}{2} \rfloor}\) 种连边方案

现在我们再考虑两个大小分别为 \(x\) 、\(y\) 的循环之间的影响

显然,若我们在 \(x\) 中的第 \(i\) 个元素与在 \(y\) 中的第 \(j\) 个元素之间连了一条边,那么对于 \((i+1,j+1),(i+2,j+2)...\) 直至 \(i\) 与 \(j\) 再次连边。那么一共要连 \(lcm(x,y)\) 条边,而我们一共有 \(xy\) 种对应方案,所以一共有 \(\frac{xy}{lcm(x,y)}\) 种边,即 \(\gcd(x,y)\) 种边,所以这些循环之间产生的贡献就是 \(2^{\gcd(x,y)}\)

那么我们现在可以考虑枚举置换 \(g\) ,设其分解成的第 \(i\) 个循环的元素集合为 \(g_i\) ,那么答案就是
\[ \frac{1}{|G|}\sum\limits_{g\in G}(\prod\limits_{i=1}^{|g|}2^{\lfloor \frac{|g_i|}{2} \rfloor}\prod\limits_{i<j\le |g|}2^{\gcd(|g_i|,|g_j|)}) \]
不幸的是,由于要枚举整个置换群,这样的复杂度是 \(O(n!)\) 的

我们换个角度考虑

可以发现,我们只关心置换在分解成若干个循环的乘积后每个循环的大小,而并不在意这些循环究竟包含了哪些元素,所以我们可以考虑枚举每个置换可能是由哪些循环乘起来的

这个可以通过搜索求出,复杂度是自然数划分的方案数,可以接受

对于一种大小为 \(k\) 的划分方案,设 \(L_i\) 表示其中第 \(i\) 个循环的长度

首先考虑为这 \(k\) 个循环安排它们的位置,这步的方案数是带重复元素的排列数,即 \(\dbinom{n}{L_1\ L_2\ L_3 \ ...\ L_k}\)

然后我们再来考虑这 \(k\) 个循环内部的安排方式

直接 \(L_i!\) 肯定是不行的,因为这样无法保证它不能再被分解成更小的循环

但其实这也很简单,我们只要每次选出一个元素并在除了它以外且没有选过的元素中选择一个就可以了,所以这一步的方案数实际上是 \((L_i-1)!\)

两式相乘,得 \(\frac{n!}{\prod\limits_{i=1}^{k}L_i}\)

但这还不止,如果我们枚举到两个大小相同的循环,那么我们会把它们交换后的方案也算上,举例而言,就是:

如果有两个循环 \((2\ 1)(4\ 3)\) ,我们把它们交换一下,有 \((4\ 3)(2\ 1)\) ,然而这两个玩意儿是本质相同的,所以如果用 \(C_i\) 来表示一个置换中长度为 \(i\) 的循环的个数,那么方案数最后还得除上 \(\prod\limits_{i=1}^{n}C_i!\)

所以我们最后得到将 \(k\) 个长度分别为 \(L_1,L_2,...,L_k\) 的循环安放进去的方案数为
\[ \frac{n!}{\prod\limits_{i=1}^{k}L_i\prod\limits_{i=1}^{n}C_i!} \]
而安放完这些循环后,我们还得再乘上之前分析过的循环内部及循环之间产生的贡献数,得到最后的答案为
\[ \sum\limits_{\ \ \sum\limits_{i=1}^{k}L_i=n,\\L_1\ge L_2\ge...\ge L_k}\frac{\prod\limits_{i=1}^{k}2^{\lfloor \frac{L_i}{2} \rfloor}\prod\limits_{i<j\le k}2^{\gcd(L_i,L_j)}}{\prod\limits_{i=1}^{k}L_i\prod\limits_{i=1}^{n}C_i!} \]
其中 \(|G|\) 与 \(n!\) 抵消了,然后直接计算即可

复杂度为 \(O(B_n\times n^2)\) ,\(B_n\) 为 \(n\) 的自然数划分的方案数

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e2+10;
const int mod=997;
int n,L[N],bin[N],fac[N],gcd[N][N],ans,C[N];
inline void Add(int &x,int y){x+=y;x-=x>=mod? mod:0;}
inline int MOD(int x){x-=x>=mod? mod:0;return x;}
inline int Minus(int x){x+=x<0? mod:0;return x;}
inline int exgcd(int x,int y){int r;if(y)swap(x,y);while(x&&y)r=x%y,x=y,y=r;return x;}
inline int fas(int x,int p){int res=1;while(p){if(p&1)res=1ll*res*x%mod;p>>=1;x=1ll*x*x%mod;}return res;}
inline void Calc(int m){int sum=1;for(register int i=1;i<=m;i++)sum=1ll*sum*bin[L[i]>>1]%mod;for(register int i=1;i<=m;i++)for(register int j=i+1;j<=m;j++)if(i!=j)sum=1ll*sum*bin[gcd[L[i]][L[j]]]%mod;int fm=1;for(register int i=1;i<=m;i++)fm=1ll*fm*L[i]%mod;memset(C,0,sizeof(C));for(register int i=1;i<=m;i++)C[L[i]]++;for(register int i=1;i<=n;i++)fm=1ll*fm*fac[C[i]]%mod;Add(ans,1ll*sum*fas(fm,mod-2)%mod);
}
inline void DFS(int rest,int las,int num){if(!rest){Calc(num-1);return;}for(register int i=1;i<=min(rest,las);i++)L[num]=i,DFS(rest-i,i,num+1);
}
inline void Preprocess(){for(register int i=1;i<=n;i++)for(register int j=1;j<=n;j++)gcd[i][j]=exgcd(i,j);fac[0]=1;for(register int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;bin[0]=1;for(register int i=1;i<=n;i++)bin[i]=2ll*bin[i-1]%mod;
}
int main(){scanf("%d",&n);if(!n){puts("1");return 0;}Preprocess();DFS(n,n,1);printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/ForwardFuture/p/11478566.html

Luogu P4727 [HNOI2009]图的同构记数相关推荐

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

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

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

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

  3. 解决CSV文件中长数字以科学记数格式保存问题

    今天因为需要做数据导入到数据表中,用xlxs文件做好了转化为csv文件,结果一看×××,傻眼了,全部变为科学记数了,在xlxs设置好的单元格格式为文本,可是转化为csv之后就变为了常规,而且×××也改 ...

  4. Vijos P1848 记数问题【进制】

    描述 试计算在区间 1 到 n 的所有整数中,数字 x(0 ≤ x ≤ 9)共出现了多少次?例如,在 1 到 11 中,即在 1.2.3.4.5.6.7.8.9.10.11 中,数字 1 出现了 4 ...

  5. Python02 标准输入输出、数据类型、变量、随记数的生成、turtle模块详解

    1 标准输出 python3利用 print() 来实现标准输出 def print(self, *args, sep=' ', end='\n', file=None): # known speci ...

  6. BZOJ1488: [HNOI2009]图的同构

    BZOJ1488: [HNOI2009]图的同构 Description 求两两互不同构的含n个点的简单图有多少种. 简单图是关联一对顶点的无向边不多于一条的不含自环的图. a图与b图被认为是同构的是 ...

  7. NC65 对上年度反结账,调整数据后重新结账后,对本年度年初重算时系统报错:更新记数错误。

    1.对上年度反结账,调整数据后重新结账后,对本年度年初重算时系统报错:更新记数错误. 解决方案: 1.在期初余额节点,按Ctrl+ALT+A重建期初凭证: 2.到结账节点,重建余额表,选择有问题的财务 ...

  8. mysql更新后变成科学记数,CONVERT函数解决

    背景: 通过sql更新某个长数字字符串字段+1,结果变成了科学记数 例如: 初始数据如下,更新id+1 执行sql: UPDATE test set id = id + 1 结果如下: 原因:数据类型 ...

  9. python用turtle输入数字_Python02 标准输入输出、数据类型、变量、随记数的生成、turtle模块详解...

    1 标准输出 python3利用print() 来实现标准输出 def print(self, *args, sep=' ', end='\n', file=None): #known special ...

  10. 记数排序 桶排序 基数排序

    为什么要写这样滴一篇博客捏...因为一个新初一问了一道水题,结果就莫名其妙引起了战斗. 然后突然发现之前理解的桶排序并不是真正的桶排序,所以写一篇来区别下这三个十分相似的排序辣. 老年菜兔的觉醒!!! ...

最新文章

  1. 生猛!PDF 版本 6000 页 Java 手册开放下载!
  2. Windows10下OpenCV_contrib安装配置
  3. variable java_在XSLT中使用Variable Argument调用Java方法
  4. 《数据结构与算法 C语言版》—— 2.5上机实验
  5. git使用的基本流程_git命令的基本使用
  6. 【CHM】.chm文件无法正常显示的解决方案
  7. matlab rand函数
  8. [转] 面试70问经典回答
  9. 按shift键调出命令行的脚本
  10. 计算机基础客户端v7,ComwareV7
  11. 农村环境保护学习资料
  12. vue移动端日历显示查看每日详情列表
  13. ASP.NET实现将word文档转换成pdf的方法
  14. 自动化测试如何计算ROI
  15. java joda 获取utc时间_Java获取时间与系统时间相差8小时终极解决方案
  16. python能调用身份证读卡器吗_最近的项目中用到读卡器,用的华视身份证阅读器,附上SDK使用手册...
  17. python培训免费视频
  18. 什么是工作流?(转贴)
  19. sql查询取第一条数据
  20. known_hosts to get rid of this message问题

热门文章

  1. Interview Tips with Consulting Firms
  2. ajax/ 回调函数(回调地狱)
  3. (13.3)Latex参考文献引用及常规引用
  4. 61种u盘问题解决工具合集解决无法格式化,u盘写保护等问题。
  5. 快速刷微信小程序访问量和浏览量
  6. android 基站信息说明,安卓android手机查看基站信息
  7. linux 查找内容对应行数,Linux查看文件指定行数内容与查找文件内容
  8. 51job简历如何导出pdf格式
  9. 利用pandas 读取pdf中的表格文件
  10. Cadence PSpice 仿真4:共射极运放静态工作点仿真图文教程