[bzoj1488][HNOI2009]图的同构——Polya定理
题目大意
求两两互不同构的含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即可。
现在假设我们已经枚举好了一个置换,那么这种置换的个数根据一些基本的排列组合知识,可以知道是:
\]
稍微解释一下这个式子。除以\(Val_i\)是因为圆形排列,除以\(Num_i\)是因为同阶循环的重复排列。
根据Polya定理,等价类的个数就是:
\]
事实上,这个题还有一个变态的做法:
就是上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定理的更多相关文章
- [BZOJ1815&BZOJ1488]有色图/图的同构(Polya定理)
由于有很多本质相同的重复置换,我们先枚举各种长度的点循环分别有多少个,这个暴搜的复杂度不大,n=53时也只有3e5左右.对于每种搜索方案可以轻易求出它所代表的置换具体有多少个. 但我们搜索的是点置换组 ...
- bzoj1488 [HNOI2009]图的同构 Burnside 引理
题目传送门 bzoj1488 - [HNOI2009]图的同构 bzoj1815 - [Shoi2006]color 有色图(双倍经验) 题解 暴力 由于在做题之前已经被告知是 Burnside 引理 ...
- bzoj1488[HNOI2009]图的同构
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1488 1488: [HNOI2009]图的同构 Time Limit: 10 Sec M ...
- BZOJ 1488: [HNOI2009]图的同构 [Polya]
完全图中选出不同构的简单图有多少个 上题简化版,只有两种颜色....直接copy就行了 太诡异了,刚才电脑上多了一个不动的鼠标指针,然后打开显卡管理界面就没了 #include<iostream ...
- 【BZOJ1488】[HNOI2009]图的同构(Burside引理,Polya定理)
[BZOJ1488][HNOI2009]图的同构(Burside引理,Polya定理) 题面 BZOJ 洛谷 题解 求本质不同的方案数,很明显就是群论这套理论了. 置换一共有\(n!\)个,考虑如何对 ...
- 【BZOJ1488】[HNOI2009]图的同构计数
题目链接 题意 求 n 个点的同构意义下不同的图的数量.\((n\leq 60)\) Sol \(Polya\) 定理的练手题. 我们这里先把边的存在与否变成对边进行黑白染色,白色代表不存在,这样就变 ...
- Polya 定理 学习笔记
群 群的定义 我们定义,对于一个集合 \(G\) 以及二元运算 \(\times\),如果满足以下四种性质,那我们就称 \((G,\times)\) 为一个群. 1. 封闭性 对于 \(a\in G, ...
- 【转】Polya定理
转自:http://endlesscount.blog.163.com/blog/static/82119787201221324524202/ Polya定理 首先记Sn为有前n个正整数组成的集合, ...
- 【群论】polya定理
对Polya定理的个人认识 我们先来看一道经典题目: He's Circles(SGU 294) 有一个长度为N的环,上面写着“X”和“E”,问本质不同的环有多少个(不 ...
随机推荐
- 《团队-Oldnote-最终程序》
托管平台地址:https://github.com/Vcandoit/Notepad 小组名称:TOP 小组成员合照:待添加 程序运行方法:手机app,安装到手机点击即可运行,打开页面会有图标提示. ...
- C语言博客作业--数组
一.PTA实验作业 题目1.求整数序列中出现次数最多的数 1.本题PTA提交列表 2.设计思路 定义整形变量n,max,count分别表示整数个数,出现次数最大值,出现次数.定义循环变量i,j. 输入 ...
- 2017-2018-1 Java演绎法 小组成员贡献量汇总
[第一周]贡献量(31) [说明] 完成情况 是指 每次是否全部完成分配的任务,如果全部完成贡献量记为1,否则记为0,与贡献量(时间量)相加计算贡献比例,由于前十周有具体的任务分配,Alpha阶段(第 ...
- 201621123050 《Java程序设计》第8周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 答:ArrayLi ...
- python 堆排序
堆排序就是把堆顶的最大数取出, 将剩余的堆继续调整为最大堆,具体过程在第二块有介绍,以递归实现 剩余部分调整为最大堆后,再次将堆顶的最大数取出,再将剩余部分调整为最大堆,这个过程持续到剩余数只有一个时 ...
- 直方图均衡化及matlab实现
在处理图像时,偶尔会碰到图像的灰度级别集中在某个小范围内的问题,这时候图像很难看清楚.比如下图: 它的灰度级别,我们利用一个直方图可以看出来(横坐标从0到255,表示灰度级别,纵坐标表示每个灰度级别的 ...
- JAVA_SE基础——40.super关键字
只要this关键字掌握了,super关键字不在话下,因为他们原理都差不多的.. this&super 什么是this,this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针 ...
- java之多态详解
前言 什么叫多态?多态就是一种事物可以有多种表现形式 多态三要素 1.被动方必须有继承关系 2.子类一般都要重写父类方法 3.必须将主动方的功能函数的参数设置为 被动方父类的类型 举个例子司机开车 假 ...
- CentOS 6.5 Tomcat安装及配置
1.安装jdk,配置jdk环境(此步骤略过) 2.下载安装tomcat 百度网盘链接: https://pan.baidu.com/s/1Ieejo7TQyzRAVPhQft8Phw 密码: dg2v ...
- Linux搭建Apache+Tomcat实现负载均衡
一.首先需要安装java,详见http://www.cnblogs.com/fun0623/p/4350004.html 二.编译安装Apache,详见http://www.cnblogs.com/f ...