1488: [HNOI2009]图的同构

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 700  Solved: 470
[Submit][Status][Discuss]

Description

求两两互不同构的含n个点的简单图有多少种。

简单图是关联一对顶点的无向边不多于一条的不含自环的图。

a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和边集能完全与b图一一对应。

Input

输入一行一个整数N,表示图的顶点数,0<=N<=60

Output

输出一行一个整数表示含N个点的图在同构意义下互不同构的图的数目,答案对997取模。

Sample Input

输入1
1

输入2
2

输入3
3

Sample Output

输出1
1

输出2
2

输出3
4

    很经典的一类等价图计数问题。。。。
    可以先等价于每条边可以染两种颜色,求两两本质不同的图的个数。。。
    最朴素的想法就是找出所有边的置换,对每个置换求一下环数,然后用p????引理算一下方案数,最后除以总置换数(也就是边数的阶乘的逆元)就可以得到答案了。。。
    但是有一些边的置换是会出现矛盾的。。。因为边置换要求两个顶点映射到新边的两个顶点上,难免会产生冲突。
    于是我们换一种思路,枚举点的置换,边的置换就随之确定了,并且会不重不漏的算上所有边的置换(想一想为什么)
    现在的问题就变成了:给你一个点的置换,问你边的置换的环数。
    先把点置换表示成若干个环的乘积,然后同一个环内部点之间的边的置换环数为 (点的)环大小/2,连接不同环之间的所有边的置换环数为 gcd(siz1,siz2)。
    理解这一步非常的关键。
   
    首先不妨将(点的)环上乱序的数写成{1,2,....,siz},这样并不影响最后的(边的)环数。
    这样 (1,i) 这条边是和任意 ( j , (j+i-1)%siz +1)的边等价的,而且当i>n/2的时候显然不合法,因为(i,1)这条边之前已经在别的等价类里被算过了。
    于是我们就求出了第一种边的置换环数。。。
    第二种的话,由于每转一圈,一个环中的点对应的另一个环中的点会产生 |siz1 - siz2|的偏位移,由同余相关定理可以很轻松的算出每个环的大小都是 siz1 * siz2 / gcd(siz1 , siz2),所以环数就是 gcd(siz1 , siz2)了。
    于是就可以A题了???
    并不,枚举排列的时候就已经超时了2333
    不过观察上述做法可以发现,一种置换的方案数之和 (点的)环的大小(可重)集合有关。
    所以我们改用??数(我也忘了叫啥了。。反正不大)的复杂度枚举一下可重集中的元素是哪些,算出了这个可重集的方案数之后再乘上可以映射到这个可重集上的排列数 加到答案里就好啦。。。。
    至于映射数?
    (组合数学入门问题,自己推推吧2333)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ha=997,mod=ha-1;inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}inline int ksm(int x,int y){int an=1;for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;return an;
}int gcd[73][73],n,ci[1005],ans,jc[73],ni[73];
int m,a[65],tot,now,C[73][73],b[65];inline void calc(){ m=0;for(int i=1;i<=n;i++)for(int j=1;j<=b[i];j++) a[++m]=i;tot=0,now=1;for(int i=1;i<=m;i++) tot+=a[i]>>1;for(int i=1;i<=m;i++)for(int j=i+1;j<=m;j++) tot+=gcd[a[i]][a[j]];if(tot>=mod) tot%=mod;for(int T=n,i=1;i<=m;T-=a[i],i++) now=now*(ll)C[T][a[i]]%ha*(ll)jc[a[i]-1]%ha;for(int i=1;i<=n;i++) if(b[i]>1) now=now*(ll)ni[b[i]]%ha;ADD(ans,now*(ll)ci[tot]%ha);
}void dfs(int x,int lef){if(lef<x){ if(!lef) calc(); return;}for(int i=0,u=0;u<=lef;i++,u+=x) b[x]=i,dfs(x+1,lef-u),b[x]=0;
}int main(){    ci[0]=1; for(int i=1;i<ha;i++) ci[i]=add(ci[i-1],ci[i-1]);jc[0]=1; for(int i=1;i<=60;i++) jc[i]=jc[i-1]*(ll)i%ha;ni[60]=ksm(jc[60],ha-2);for(int i=60;i;i--) ni[i-1]=ni[i]*(ll)i%ha;    C[0][0]=1;for(int i=1;i<=60;i++){C[i][0]=1;for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);}scanf("%d",&n);for(int i=0;i<=n;i++)for(int j=0;j<=i;j++)if(!i||!j) gcd[i][j]=i+j;else gcd[j][i]=gcd[i][j]=gcd[j][i%j];dfs(1,n),ans=ans*(ll)ni[n]%ha;printf("%d\n",ans);return 0;
}

  

转载于:https://www.cnblogs.com/JYYHH/p/9245045.html

[HNOI2009] 图的同构相关推荐

  1. BZOJ1488: [HNOI2009]图的同构

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

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

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

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

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

  4. BZOJ 1488 [HNOI2009]图的同构 Polya定理

    题意:链接 方法: Polya定理 解析: 先扯点题外话. 小雨淅沥的下午,PoPoQQQ爷在屠了一道题后放松心情,恰看见我把知识点上的群论标记已会. 于是,为了发扬D人的精神,PoPoQQQ爷打开了 ...

  5. 《小学生都能看懂的群论从入门到升天教程》 《群论全家桶》

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 小学生都能看懂系列,小学生:我太难了   群论.置换.Bunrnside引理.Pόlya定理等概念是群 ...

  6. P3201 [HNOI2009]梦幻布丁 [启发式合并][set]

    P3201 [HNOI2009]梦幻布丁 题意:N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3 ...

  7. [HNOI2009]最小圈 (二分答案+负环)

    题面:[HNOI2009]最小圈 题目描述: 考虑带权的有向图\(G=(V,E)\)以及\(w:E\rightarrow R\),每条边\(e=(i,j)(i\neq j,i\in V,j\in V) ...

  8. 【BZOJ1485】[HNOI2009]有趣的数列(组合数学)

    [BZOJ1485][HNOI2009]有趣的数列(组合数学) 题面 BZOJ 洛谷 题解 从小往大填数,要么填在最小的奇数位置,要么填在最小的偶数位置. 偶数位置填的数的个数不能超过奇数位置填的数的 ...

  9. P4728 [HNOI2009]双递增序列

    链接P4728 [HNOI2009]双递增序列 设\(f_{i,j}\)表示当前考虑第\(i\)个数,上一步是\(a_{i-1}\)接在后面的序列一共取了\(j\)个数,另外一个序列的末尾最小值. 转 ...

  10. 「BZOJ1485」[HNOI2009] 有趣的数列 (卡特兰数列)

    「BZOJ1485」[HNOI2009] 有趣的数列   Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai ...

最新文章

  1. 啥都不如烂笔头,约翰霍普金斯大学新研究:学外语还得用手写
  2. 机器学习:分类器介绍
  3. 用数组实现从文件搜索帐户和验证密码
  4. SpringBoot中Mybatis打印sql日志
  5. qt: 获取sql数据表的所有的字段;
  6. python测试udp端口_怎样测试UDP端口
  7. Hibernate使用原生SQL适应复杂数据查询
  8. Python html 代码转成 word(docx)
  9. 1064金明的预算方案
  10. OAuth2.0_授权服务配置_三项内容_Spring Security OAuth2.0认证授权---springcloud工作笔记141
  11. 基于序列图像的三维体绘的视线投射算法
  12. Win7 安装程序时报错 error 1935 HRESULT 0x80070422
  13. 谷歌 kaptcha 图片验证码
  14. 电视盒子刷鸿蒙系统,当贝市场亲测有效三款获取电视和盒子root权限的工具应用...
  15. Chemex 打印标签二维码扫不出信息,跳转地址不正确404,如何改代码?
  16. 拆分pdf文件最简单的方法
  17. 2018.11.07 NOIP训练 lzy的游戏(01背包)
  18. 如何在Android设备上识别读取美国驾照信息
  19. 真实经历!运维安全工程师经典面试汇总
  20. 【haoi2009】毛毛虫

热门文章

  1. 计算机网络计算1g等于多少MB,1g是多少mb(1g等于多少兆)
  2. 如何快速学习整车控制器VCU电控开发
  3. python制作表情,使用Python制作滑稽表情
  4. 鼠标右键中新建选项消失
  5. C 语言编程计算年龄,C#实现计算年龄的简单方法汇总
  6. python已停止工作请关闭该程序_解决PyCharm的Python.exe已经停止工作的问题
  7. DocumentFormat.OpenXml
  8. 使用APICloud AVM多端组件快速实现app中的搜索功能
  9. spurious wakeup 虚假唤醒
  10. 解决布局点击事件穿透的问题