洛谷题面传送门

神仙题 %%%%%%%%%%%%%%%%%%%%

题解搬运人来了

首先看到本质不同(无标号)的图计数咱们可以想到 Burnside 引理,具体来说,我们枚举一个排列 \(p\),并统计有多少张图中的点集在置换 \(p\) 的作用下能够保持不变,记这个数目为 \(c(p)\),那么答案就是 \(\dfrac{1}{n!}\sum\limits_{p}c(p)\)。由于此题 \(n\) 高达 \(50\),因此暴力枚举 \(p\) 显然是不合理的,不过注意到合法的图的数量并不取决于 \(p\) 具体每个元素是什么,而取决于 \(p\) 中每个置换环的大小分别是多少,而 \(50\) 的整数拆分数量并不是很多,因此考虑枚举 \(p\) 中置换环的大小,设为 \(s_1,s_2,s_3,\cdots,s_k\),其中 \(s_1<s_2<\cdots<s_k\),那么符合条件的排列 \(p\) 的个数可以这样计算:

  • 首先,对于所有置换环选出属于该置换环的 \(s_i\) 个点,这显然是一个多重组合数的形式,方案数为 \(\dfrac{n!}{\prod\limits_{i=1}^ks_i!}\)。
  • 其次,每个置换环,根据圆排列的计数方法,将其进行排列有 \((s_i-1)!\)​ 种方案,因此还需乘上个 \(\prod\limits_{i=1}^k(s_i-1)!\)​
  • 再其次,所有大小相同的置换环是视作相同的,因此假设大小为 \(x\)​ 的置换环有 \(cnt_x\)​ 个,那么答案还需除以 \(\prod\limits_{i=1}^{s_k}cnt_i!\)

因此对于一组大小分别为 \(s_1,s_2,\cdots,s_k\)​​ 的置换环,有 \(\dfrac{n!}{\prod\limits_{i=1}^ks_i!\prod\limits_{i=1}^{s_k}cnt_i!}·\prod\limits_{i=1}^k(s_i-1)!\)​​ 个排列 \(p\),满足其置换环的大小组成的集合恰好是 \(\{s_1,s_2,\cdots,s_k\}\)

接下来考虑如何计算对于一个置换环大小分别为 \(s_1,s_2,\cdots,s_k\) 的置换 \(p\)​,有多少张图满足其在 \(p\) 的作用下能够保持同构且每个连通块都有欧拉回路,即每个点的度都是偶数。考虑分两部分处理:

  1. 每个置换环内部点与点之间的边
  2. 置换环与置换环之间的边

首先对于第一部分而言,假设我们考虑第 \(i\)​​ 个置换环,那么显然图在 \(p\)​​ 的作用下保持同构的必要条件是第 \(i\)​​ 个置换环中所有距离相同的边存在/不存在的状态都相同,我们先不考虑每个点度都要是偶数这个条件,那么显然有 \(2^{\lfloor\dfrac{s_i}{2}\rfloor}\)​​ 种连边的情况,接下来考虑加上每个点度都要是偶数这个条件后怎么处理,不难发现,对于一般的情况,距离为 \(d\)​​ 的边都连上是不影响这个连通块中所有点的奇偶性的,唯独一种情况——\(d=\dfrac{s_i}{2}\)​​,且 \(s_i\)​​ 为偶数的情况,这种情况下,这个置换环中所有点度数的奇偶性都会反转,也就是说对于 \(s_i\)​​ 是偶数的情况,选择另外 \(d\)​ 种距离的方案数为 \(2^{\lfloor\dfrac{s_i}{2}\rfloor-1}\)​ 种,而对于 \(d=\dfrac{s_i}{2}\)​​ 的情况,相当于我们给了这个连通块一次改变所有点奇偶性的机会,可选可不选。

接下来考虑不同置换环之间连边的方案,我们假设现在考虑了编号为 \(i,j\)​ 的两个置换环,那么考虑将两个置换环上的点顺次编号 \(0,1,2,3,\cdots,s_i-1\)​ 以及 \(0,1,2,3,\cdots,s_j-1\)​。考虑记 \(d=\gcd(s_i,s_j)\)​,那么显然,图在 \(p\)​ 的作用下保持同构的必要条件是对于第 \(i\)​ 个置换环上的点 \(x\)​ 和第 \(j\)​ 个置换环上的点 \(y\)​ 而言,将 \((x,y)\)​ 沿着置换环旋转得到的所有点对的连边状况都与 \((x,y)\)​ 的连边状况相同,而对于所有 \((x,y)\)​,转 \(\dfrac{s_is_j}{\gcd(s_i,s_j)}=\text{lcm}(s_i,s_j)\)​ 步就能转回原位,因此有 \(\dfrac{s_is_j}{s_is_j/\gcd(s_i,s_j)}=\gcd(s_i,s_j)=d\)​ 个本质不同的二元组。接下来考虑每个点度必须要是偶数这个条件,显然对于第 \(i\)​ 个置换环上的每个点 \(x\)​,包含 \(x\)​ 的二元组恰有 \(s_j\)​ 个,而这当中又会有 \(d\)​ 组二元组能够通过旋转得到,因此将这 \(d\)​ 个本质不同的二元组中任意一组连上,都会导致第 \(i\)​ 个置换环上每一个点多连出 \(\dfrac{s_j}{d}\)​ 条边,同理也会使第 \(j\)​ 个置换环上每一个点多连出\(\dfrac{s_i}{d}\)​ 条边。记 \(x_1=\dfrac{s_j}{d},x_2=\dfrac{s_i}{d}\),现在考虑分情况讨论:

  • 如果 \(x_1,x_2\) 都是偶数,那么显然这 \(d\) 个二元组不对两个置换环中任何一个点的度数的奇偶性产生影响,也就是说这 \(d\) 组边连与不连皆可,方案数乘上 \(2^d\)
  • 如果 \(x_1\)​ 为偶数,\(x_2\)​ 为奇数,那么连上这 \(d\)​ 个二元组中的一个不对第 \(i\)​ 个置换环中任何一个点的度数的奇偶性产生影响,但会改变第 \(j\)​ 个连通块中所有点的奇偶性,也就相当于我们给了第 \(j\)​ 个连通块 \(d\)​​ 次改变所有点奇偶性的机会。
  • 如果 \(x_1\)​ 为奇数,\(x_2\)​ 为偶数,类似于上面的情况,不过这次是我们给第 \(i\)​ 个连通块 \(d\)​ 次改变所有点奇偶性的机会
  • 如果 \(x_1,x_2\) 都是奇数,那么连上这 \(d\) 个二元组中的一个会同时改变第 \(i\) 个和第 \(j\) 个置换环中所有点度数的奇偶性,也就是说给了 \(d\) 次同时改变置换环 \(i,j\)​ 所有点奇偶性的机会。

这样问题就转化为这样一个问题

有一张 \(k\) 个点的图,点上有点权,初始每个点点权为 \(0\),每个点 \(i\) 上有 \(cp_i\) 个不同的开关,拉上这 \(cp_i\) 个开关中的任何一个都会使第 \(i\) 个点的点权异或 \(1\);每条边 \((i,j)\) 上有 \(ce_{i,j}\) 个不同的开关,拉上这 \(ce_{i,j}\) 个开关中的任何一个都会使 \(i,j\) 的点权同时异或 \(1\),问有多少个拉开关的集合,满足拉上这些开关,能够使每个点点权都是 \(0\)。

这里有一个性质,就是对于所有连通块而言:

  • 我们考虑找出连通块的一棵 DFS 树(这里 DFS 树的定义为,将所有点对 \((i,j)\) 之间连上 \(ce_{i,j}\) 条边后图的 DFS 树,也就是如果两点间有多条边那么最多只能有一条边在 DFS 树上),如果我们确定了所有非树边的状态,那么树边的状态已经唯一确定了,具体方案就是从叶子开始,如果叶子权值为 \(1\) 就拉上与叶子相连那条边上的开关,否则不拉,然后删去那个叶子。
  • 能够将连通块中所有点点权变为 \(0\)​ 还有一个必要条件,就是对点的操作的数量必须是偶数,因为对边的操作不会改变连通块中所有点权的异或和。

也就是说假设 \(S_p\) 为这个连通块中所有点 \(cp\) 之和,\(S_e\) 为这个连通块两两之间 \(ce\) 之和,\(S\) 为该连通块的点数,那么方案数就是

\[2^{\max(S_p-1,0)+S_e-(S-1)}
\]

并查集维护一下即可。

时间复杂度 \(\mathcal O(\text{Can pass})\).

const int MAXN=50;
const int MOD=998244353;
int n,fac[MAXN+5],ifac[MAXN+5],pw2[MAXN*MAXN*MAXN+5];
int g[MAXN+5][MAXN+5];
void init_fac(){
for(int i=(pw2[0]=fac[0]=ifac[0]=ifac[1]=1)+1;i<=MAXN;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=MAXN;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
for(int i=1;i<=MAXN*MAXN*MAXN;i++) pw2[i]=(pw2[i-1]<<1)%MOD;
}
int s[MAXN+5],cnt[MAXN+5],ans=0;
int f[MAXN+5],c1[MAXN+5],c2[MAXN+5],siz[MAXN+5];
int find(int x){return (!f[x])?x:f[x]=find(f[x]);}
void merge(int x,int y,int z){
x=find(x);y=find(y);
if(x==y) c2[x]+=z;
else{
if(siz[x]<siz[y]) swap(x,y);
f[y]=x;siz[x]+=siz[y];
c1[x]+=c1[y];c2[x]+=c2[y];
c2[x]+=z;
}
}
int calc(int k){
int res=1;
for(int i=1;i<=k;i++) res=1ll*res*ifac[s[i]]%MOD*fac[s[i]-1]%MOD;
for(int i=1;i<=n;i++) res=1ll*res*ifac[cnt[i]]%MOD;
memset(f,0,sizeof(f));memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));
for(int i=1;i<=k;i++) siz[i]=1;
for(int i=1;i<=k;i++){
res=1ll*res*pw2[s[i]-1>>1]%MOD;
if(~s[i]&1) c1[i]++;
}
for(int i=1;i<=k;i++) for(int j=i+1;j<=k;j++){
int d=g[s[i]][s[j]];
int d1=s[j]/d,d2=s[i]/d;
if((~d1&1)&&(~d2&1)) res=1ll*res*pw2[d]%MOD;
else if((d1&1)&&(d2&1)) merge(i,j,d);
else if(d1&1) c1[find(i)]+=d;
else c1[find(j)]+=d;
}
for(int i=1;i<=k;i++) if(find(i)==i){
res=1ll*res*pw2[max(c1[i]-1,0)+c2[i]-siz[i]+1]%MOD;
}
// for(int i=1;i<=k;i++) printf("%d%c",s[i]," \n"[i==k]);
// printf("%d\n",res);
return res;
}
void dfs(int x,int sum,int pre){
if(sum==n) return ans=(ans+calc(x-1))%MOD,void();
for(int i=pre;sum+i<=n;i++){
s[x]=i;cnt[i]++;dfs(x+1,sum+i,i);cnt[i]--;
}
}
int main(){
scanf("%d",&n);init_fac();
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
g[i][j]=__gcd(i,j);
dfs(1,0,1);printf("%d\n",ans);
return 0;
}

洛谷 P4708 - 画画(Burnside 引理+组合数学)的更多相关文章

  1. 洛谷 P4708 画画(无标号欧拉子图计数)

    首先还是类似于无标号无向图计数那样,考虑点的置换带动边的置换,一定构成单射,根据 Burnside 引理: \[|X / G| = \frac{1}{|G|}\sum\limits_{g \in G} ...

  2. Luogu P4708 画画 (Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P4708 题解 看上去Luogu P4706-4709是Sdchr神仙出的一场比赛,一道水题和三道很有趣的题终于全过了纪念QAQ ...

  3. 洛谷 P4708 画画

    题意 在所以置换下,本质不同的各个极大连通子图均含有欧拉闭迹的\(n\)阶图个数 做法 务必先做完这题再看此题解,因为会省略大部分分析了 仍是从边入手,隔外限制:各个点度数是偶数 某个因子内\((m= ...

  4. 洛谷P3158 [CQOI2011]放棋子 组合数学+DP

    题意:在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同颜色的棋子不能在同一行或者同一列.有多少祌方法? 解法:这道题不会做,太菜了qwq.题解是看洛谷大佬的. 设C是组合数, ...

  5. 洛谷 - P2181 - 对角线 - 打表 - 组合数学

    https://www.luogu.org/problemnew/show/P2181 对于某条对角线,除去从两端出发的对角线,其他的都与它有1个交点. 每个点有(n-3)条对角线,每条对角线和其余C ...

  6. 洛谷P4104 [HEOI2014]平衡(dp 组合数学)

    题意 题目链接 Sol 可以把题目转化为从\([1, 2n + 1]\)中选\(k\)个数,使其和为\((n+1)k\). 再转化一下:把\((n+1)k\)划分为\(k\)个数,满足每个数在范围在\ ...

  7. 洛谷P4071 [SDOI2016] 排列计数 [组合数学]

    题目传送门 排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m ...

  8. 洛谷P3643 [APIO2016]划艇(组合数学)

    题面 传送门 题解 首先区间个数很少,我们考虑把所有区间离散化(这里要把所有的右端点变为\(B_i+1\)代表的开区间) 设\(f_{i,j}\)表示考虑到第\(i\)个学校且第\(i\)个学校必选, ...

  9. 洛谷P2606 [ZJOI2010]排列计数 组合数学+DP

    题意:称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大, ...

随机推荐

  1. 分割迭代器Spliterator源码文档翻译

    前言 身体是革命的本钱,不舒服了2周,现在好点了. 学习JDK8的Stream,Spliterator这个分割迭代器是必须要重视的. Notes:下方蓝色文字是自己的翻译(如果有问题请指正).黑色文字 ...

  2. jdbc简单学生管理系统

    这个是java连接mysql数据库的一个简单学生系统,通过jdbc连接数据库. 工具类 JDBCuntils. package Student; import java.io.IOException; ...

  3. 【UE4 C++】 Config Settings配置文件(.ini)

    简介 常见存储路径 \Engine\Config\ \Engine\Saved\Config\ (运行后生成) [ProjectName]\Config\ [ProjectName]\Saved\Co ...

  4. 第六次Scrum Metting

    日期:2021年5月3日 会议主要内容概述:讨论前后端进度,前端各模块对接以及前后端对接. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 数据模块 ...

  5. [no code] Scrum Meeting 博客目录

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Scrum Meeting博客目录 我们在这个课程的目标是 远程协同工作,采用最新技术 ...

  6. seata整合nacos完成分布式的部署

    seata整合nacos完成分布式的部署 一.背景 二.部署机器 三.部署步骤 1.在seata上创建命名空间 2.下载对应版本的seata 3.单机启动 1.修改seata配置文件 1.修改注册中心 ...

  7. 2021.1.8 NKOJ 周赛总结

    意料之中..... A:nkoj 3900 AC小程序 http://oi.nks.edu.cn/zh/Problem/Details/3900 A题比较简单,单独分析一下A和C,其实就是一个斐波那契 ...

  8. Linux过来人帮你理清学习思路

    很多同学接触linux不多,对linux平台的开发更是一无所知. 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机it行业从业人员,="" 掌握linux是一种很重要的 ...

  9. 21.10.14 test

    题目 WOJ5078 到 WOJ5081 T1 Problem A \(\color{green}{100}\) 由于每轮要选择尽量多的边删除,所以想到无向图的生成树,因为在生成树上再加一条边就会形成 ...

  10. js计算精确度丢失问题解决

    (function () { var calc = { /* 函数,加法函数,用来得到精确的加法结果 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精 ...