题目大意

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

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

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

题解

这个题是学习了Polya定理和群论以后的练手题,但是推了好久并没有推出来。。。。真的是太难辣。。。

首先我先说一下我错误的想法:

很容易就把这个题转化成了给\(K_n\)的完全图上的边进行二着色的问题,然后,由于在组合数学课程中经常接触到多边形着色,所以我就把这个题错误的转化成了在一个正\(\frac{n(n-1)}{2}\)边形的顶点上进行二着色的问题。然而对于n=1,2,3这种方法都是可行的,但是到了n=4的情况,这种方法就不可行了。我仔细观察了一下,发现这个转化不符合满足纯粹性和完备性。。。

然后就说一下正解吧。

首先我们考虑n = 4的情况,对于\(K_4\)进行二着色,我们很容易发现,由于图是可以任意扭转的,所以它的置换群实际上是一个对称群

那么对于点的每一个置换我们要计算对应的边的置换。

在一个置换中,考察一条边,如果这条边的两个节点位于相同的循环中,那么我们可以得出边的循环个数是点的循环个数的一半。

如果这条边的两个节点位于不同的循环中,那么我们画一画图就可以知道如果点的循环个数分别是a, b,那么边的循环个数就是gcd(a,b)。

根据这样的方法,我们就可以把点的置换转化为边的置换了。

下面的任务就是要枚举置换。

如果直接暴力,复杂度很高。

我们考虑这样的枚举(回溯)方法:

依次考虑每一种阶的循环的个数,然后暴力dfs即可。

现在假设我们已经枚举好了一个置换,那么这种置换的个数根据一些基本的排列组合知识,可以知道是:

\[\frac{n!}{\prod_{i = 1}^{cnt} Val_i * Num_i !}
\]

稍微解释一下这个式子。除以\(Val_i\)是因为圆形排列,除以\(Num_i\)是因为同阶循环的重复排列。

根据Polya定理,等价类的个数就是:

\[l = \frac{1}{N!} * \sum 2^m
\]

参考题解

事实上,这个题还有一个变态的做法:

就是上OEIS上查询通项公式。。。。

代码

#include <bits/stdc++.h>
const int mod = 997;
const int maxn = 1010;
using namespace std;
int n, cnt, ans;
int two[maxn], factor[maxn], val[maxn], num[maxn];
int pow(int n, int m) {
int ans = 1;
int b = m;
while(b) {
if(b & 1) ans = (ans * n) % mod;
b >>= 1;
n = (n*n) % mod;
}
return ans;
}
int inv(int n) {
return pow(n, mod-2);
}
int gcd(int a, int b) {
if(b == 0) return a;
else return gcd(b, a%b) % mod;
}
void init() {
factor[0] = factor[1] = two[0] = 1;
for(int i = 2; i <= 1000; i++) {
factor[i] = ((i % mod) * factor[i-1]) % mod;
}
for(int i = 1; i <= 1000; i++) {
two[i] = (two[i-1] * 2) % mod;
}
}
void dfs(int now_num, int left) {
if(left == 0) {
int sum1 = 0, sum2 = 1;
//sum1:这一种置换的循环个数
//sum2:这一种置换的个数
for(int i = 1; i <= cnt; i++) {
sum1 += (num[i] * (num[i] - 1) / 2 * val[i]) + (val[i]/2 * num[i]);
//前一部分:对于同一种循环中的不同循环的边的处理
for(int j = i + 1; j<= cnt; j++) {
sum1 += num[i] * num[j] * gcd(val[i], val[j]);
}
}
for(int i = 1; i <= cnt; i++) {
sum2 = (sum2 * pow(val[i], num[i])%mod*factor[num[i]])%mod;
}
sum2 = inv(sum2) * factor[n] % mod;
ans = (ans + pow(2, sum1) * sum2 % mod) % mod;
}
if(now_num > left) return;
dfs(now_num+1, left);
//这里的dfs放到外面可以降低常数:
//如果放在for循环里面,那么num数组中会多出许多0
//浪费时间。
for(int i = 1; i * now_num <= left; i++) {
val[++cnt] = now_num, num[cnt] = i;
dfs(now_num+1, left - i * now_num);
cnt--; //回溯
}
} int main() {
scanf("%d", &n);
init();
dfs(1, n);
ans = (ans * inv(factor[n])) % mod;
printf("%d", ans);
return 0;
}

[bzoj1488][HNOI2009]图的同构——Polya定理的更多相关文章

  1. [BZOJ1815&BZOJ1488]有色图/图的同构(Polya定理)

    由于有很多本质相同的重复置换,我们先枚举各种长度的点循环分别有多少个,这个暴搜的复杂度不大,n=53时也只有3e5左右.对于每种搜索方案可以轻易求出它所代表的置换具体有多少个. 但我们搜索的是点置换组 ...

  2. bzoj1488 [HNOI2009]图的同构 Burnside 引理

    题目传送门 bzoj1488 - [HNOI2009]图的同构 bzoj1815 - [Shoi2006]color 有色图(双倍经验) 题解 暴力 由于在做题之前已经被告知是 Burnside 引理 ...

  3. bzoj1488[HNOI2009]图的同构

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1488 1488: [HNOI2009]图的同构 Time Limit: 10 Sec  M ...

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

    完全图中选出不同构的简单图有多少个 上题简化版,只有两种颜色....直接copy就行了 太诡异了,刚才电脑上多了一个不动的鼠标指针,然后打开显卡管理界面就没了 #include<iostream ...

  5. 【BZOJ1488】[HNOI2009]图的同构(Burside引理,Polya定理)

    [BZOJ1488][HNOI2009]图的同构(Burside引理,Polya定理) 题面 BZOJ 洛谷 题解 求本质不同的方案数,很明显就是群论这套理论了. 置换一共有\(n!\)个,考虑如何对 ...

  6. 【BZOJ1488】[HNOI2009]图的同构计数

    题目链接 题意 求 n 个点的同构意义下不同的图的数量.\((n\leq 60)\) Sol \(Polya\) 定理的练手题. 我们这里先把边的存在与否变成对边进行黑白染色,白色代表不存在,这样就变 ...

  7. Polya 定理 学习笔记

    群 群的定义 我们定义,对于一个集合 \(G\) 以及二元运算 \(\times\),如果满足以下四种性质,那我们就称 \((G,\times)\) 为一个群. 1. 封闭性 对于 \(a\in G, ...

  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. scrapy 博客爬取

    item.py import scrapy class FulongpjtItem(scrapy.Item): # define the fields for your item here like: ...

  2. Echarts柱状图实现不同颜色渐变色

    第一次写文,只是想记录一下自己平时发现的小功能,这篇主要是实现echarts柱状图,每个柱子实现不同颜色的渐变色,也是第一次接触echarts,后台使用ssm,前台是extjs,直接上效果图 直接上j ...

  3. Nginx配置小结

    前两天区听了一堂Nginx的课,然后翻了一下自己之前的Nginx的笔记,做了一个简单的小结. 全局变量 $args : 这个变量等于请求行中的参数,同$query_string $content_le ...

  4. token 验证

    组件: https://jwt.io/#libraries-io

  5. EasyUI 修改 Messager 消息框大小

    需求是要修改确认消息窗口的大小. 简单的调用方法是这样的: $.messager.confirm('操作确认', '确定批量编辑文章?', function (r) { ... } 这个时候生成的弹窗 ...

  6. ArrayList源码学习----JDK1.7

    什么是ArrayList? ArrayList是存储一组数据的集合,底层也是基于数组的方式实现,实际上也是对数组元素的增删改查:它的主要特点是: 有序:(基于数组实现) 随机访问速度快:(进行随机访问 ...

  7. Python-面向对象(二)-Day7

    1.字段 12.方法 43.属性 63.1.属性的基本使用 73.2.实例:对于主机列表 83.3.属性的两种定义方式 94.对于类的成员而言都有两种形式: 144.1.私有成员和公有成员的访问限制不 ...

  8. sts 和 lombok

    1.安装lombok.jar到sts.exe所在目录 如果是eclipse,需要放到eclipse.exe所在目录,同理myeclipse. 2.修改sts.ini配置使用lombok 如果是ecli ...

  9. emqtt 试用(五)emq 的用户密码认证

    MQTT 认证设置 EMQ 消息服务器认证由一系列认证插件(Plugin)提供,系统支持按用户名密码.ClientID 或匿名认证. 系统默认开启匿名认证(anonymous),通过加载认证插件可开启 ...

  10. kubernetes进阶(01)kubernetes的namespace

    一.Namespace概念 Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组. 常见的pods, services, replication co ...