题目大意

求两两互不同构的含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. 201621123050 《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截图你的表设计. 答 ...

  2. Bate版敏捷冲刺报告--day0

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  3. 2018年3月份的PTA(一)

    写程序证明p++等价于(p)++还是等价于(p++)? 由程序说明p++等价于(p)++,因为(p++)在程序中是没有地址的,而输出中p++和(p)++的地址不同是由于在线C语言开发环境地址是动态的 ...

  4. tornado httpserver

    # coding:utf-8 import tornado.web import tornado.ioloop import tornado.httpserver # 新引入httpserver模块 ...

  5. 【Swift】Runtime动态性分析

    Swift是苹果2014年发布的编程开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序.Swift已经开源,目前最新版本为2.2.我们知道Objec ...

  6. animation & @keyframes 实现loading效果

    效果图截图如下: 直接上代码: html <!DOCTYPE html> <html> <head> <meta charset="utf-8&qu ...

  7. 码农、黑客和2B程序员之间的区别

    码农: 黑客: 2B程序员: 求2的32次方: 码农: System.out.println(Math.pow(2, 32)); 黑客: System.out.println(1L<<32 ...

  8. 分布式系统之消息中间件rabbitmq

    分布式系统之消息中间件rabbitmq 博客分类: 感谢:  一般php 用rabbitmq  java 用activemq  http://spartan1.iteye.com/blog/11802 ...

  9. Class-Based-View(CBV)

    我们都知道,Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承.封装.多态).所以Django在后来加入了Class-Based-View.可以让我们用类写V ...

  10. Spring Security 入门(1-5)Spring Security - 匿名认证

    匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...