题意

在所以置换下,本质不同的各个极大连通子图均含有欧拉闭迹的\(n\)阶图个数

做法

务必先做完这题再看此题解,因为会省略大部分分析了

仍是从边入手,隔外限制:各个点度数是偶数

  • 某个因子内\((m=a_i)\)

    如果\(m\)是奇数,等价类的边集构成了若干个环,对度数的奇偶性不发生影响

    是偶数,边\((1,1+\frac{m}{2})\)所处的等价类对各个点奇偶性都会改变,其他等价类不变
  • 两个因子\((m_1=a_i,m_2=a_j,i\neq j)\),

    \(d=(m_1,m_2)\)个等价类,每个等价类\(a_i\)中的每一点连出\(\frac{m_2}{d}\)条边,中的每一点连出\(\frac{m_1}{d}\)条边

    如果均为偶数,则不发生影响

    如果有一方为偶数(因为一方每个点连出的边数相同,将这方当做一个大点),看作另一方能凭空\(d\)次改变奇偶性

    如果两方均不为偶数,则这两大点之间连\(d\)条边

现在题目转化为

\(M\)条边的\(N\)阶图,除\(M\)条边外,每个点有\(a_i\)个环(不过每个环仅为该点度数加\(1\)),求保存一些边,使得每个点度数为偶数的方案数

然后这里求方案数有个简单结论,不是重点,就不细说了,各位去看其他题解吧

题外话

代码改了很多次,不太可看的样子(惨不忍睹)

code

#include<bits/stdc++.h>
typedef int LL;
#define pb push_back
#define opt operator
const LL maxn=60+9,mod=998244353;
LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
}return x*f;
}
LL T,n,ans,tot;
LL a[maxn],fa[maxn],fac2[maxn*maxn],fac[maxn],fav[maxn],sumd[maxn],sume[maxn],gcd[maxn][maxn],num[maxn],size[maxn];
LL Pow(LL base,LL b){
LL ret(1);
while(b){
if(b&1) ret=1ll*ret*base%mod; base=1ll*base*base%mod; b>>=1;
}return ret;
}
LL Find(LL x){ return fa[x]==x?x:fa[x]=Find(fa[x]); }
void Check(){
tot=0;
LL ret(1);
for(LL i=1;i<=n;++i){
for(LL j=1;j<=num[i];++j) a[++tot]=i;
}
for(LL i=1;i<=tot;++i){
if(a[i]&1) ret=1ll*ret*fac2[a[i]/2]%mod;
else ret=1ll*ret*fac2[a[i]/2-1]%mod,sumd[i]=1;
fa[i]=i; size[i]=1;
}
for(LL i=1;i<=tot;++i){
for(LL j=i+1;j<=tot;++j){
LL a1(a[i]),a2(a[j]);
LL g(gcd[a1][a2]),b1(a2/g),b2(a1/g); b1&=1; b2&=1;
LL fx(Find(i)),fy(Find(j));
if(b1 && b2){
if(fx!=fy) sume[fy]+=sume[fx],sumd[fy]+=sumd[fx],size[fy]+=size[fx];
fa[fx]=fy;
sume[fy]+=g;
}else if(b1) sumd[fx]+=g;
else if(b2) sumd[fy]+=g;
else ret=1ll*fac2[g]*ret%mod;
}
}
for(LL i=1;i<=tot;++i){
if(Find(i)==i){
ret=1ll*ret*fac2[sume[i]-size[i]+1]%mod;
if(sumd[i]) ret=1ll*ret*fac2[sumd[i]-1]%mod;
}
}
LL ret1(fac[n]);
for(LL i=1;i<=tot;++i){
ret1=1ll*ret1*fav[a[i]]%mod*fac[a[i]-1]%mod;
}
for(LL i=1;i<=n;++i) ret1=1ll*ret1*fav[num[i]]%mod;
ret=1ll*ret*ret1%mod;
for(LL i=1;i<=tot;++i) sumd[i]=sume[i]=0;
ans=(1ll*ans+ret)%mod;
}
void Dfs(LL x,LL N){
if(x==1){
num[x]=N; Check(); return;
}
for(LL i=0;i*x<=N;++i){
num[x]=i; Dfs(x-1,N-i*x);
}
}
int main(){
n=Read();
fac2[0]=1; for(LL i=1;i<=n*n;++i) fac2[i]=2ll*fac2[i-1]%mod;
fac[0]=1; for(LL i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
fav[n]=Pow(fac[n],mod-2); for(LL i=n;i>=1;--i) fav[i-1]=1ll*fav[i]*i%mod;
for(LL i=1;i<=n;++i) gcd[i][0]=gcd[0][i]=i;
for(LL i=1;i<=n;++i){
gcd[i][i]=i;
for(LL j=i+1;j<=n;++j){
gcd[i][j]=gcd[j][i]=gcd[i][j%i];
}
}
Dfs(n,n);
ans=1ll*ans*fav[n]%mod;
printf("%d\n",ans);
return 0;
}

洛谷 P4708 画画的更多相关文章

  1. 洛谷 P4708 - 画画(Burnside 引理+组合数学)

    洛谷题面传送门 神仙题 %%%%%%%%%%%%%%%%%%%% 题解搬运人来了 首先看到本质不同(无标号)的图计数咱们可以想到 Burnside 引理,具体来说,我们枚举一个排列 \(p\),并统计 ...

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

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

  3. 洛谷CF264D Colorful Stones(子序列匹配,思维)

    洛谷题目传送门 神仙思维题. 对于两个字符串的匹配问题,似乎之前蒟蒻写的HAOI2010最长公共子序列题解中提到的建网格图模型是一种套路? 给一个稍微强一点的样例(把字母换成了ABC) AABCB B ...

  4. Bzoj3566/洛谷P4284 [SHOI2014]概率充电器(概率dp)

    题面 Bzoj 洛谷 题解 首先考虑从儿子来的贡献: $$ f[u]=\prod_{v \in son[u]}f[v]+(1-f[v])\times(1-dis[i]) $$ 根据容斥原理,就是儿子直 ...

  5. tarjan算法比较详细的讲解&&tarjan常见疑难解答&&洛谷P2002 消息扩散题解

    因为有大佬写的比我更长更具体,所以我也就写写总结一下了 引入: 众所周知,很多图中有个东西名叫环. 对于这个东西很多算法都很头疼.(suchas 迪杰斯特拉) 更深层:环属于强联通分量(strongl ...

  6. 题解 洛谷P1990 覆盖墙壁

    DP康复训练题 原题:洛谷P1990 核心:递推/DP 题源应该是铺地砖,所以采用一摸一样的思路,只是有两种不同的方块 我们先用最最简单的方式尝试一下枚举当最后一行被填满的情况: 1.如果我们只用第一 ...

  7. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  8. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  9. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

随机推荐

  1. Go语言实现:【剑指offer】对称的二叉树

    该题目来源于牛客网<剑指offer>专题. 请实现一个函数,用来判断一颗二叉树是不是对称的.注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的. Go语言实现: 方法一:递归 / ...

  2. Go语言实现:【剑指offer】数据流中的中位数

    该题目来源于牛客网<剑指offer>专题. 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位 ...

  3. 带你简单了解域名系统DNS

    带你简单了解域名系统DNS 一.域名简介 1.1.DNS服务的作用 负责解析域名,将域名解析成IP地址. 1.2.域名系统概述 由于32位的IP地址并不容易记忆,人们往往喜欢记忆网站的域名.所以当我们 ...

  4. JAVA ReentrantLock的使用

    源码如下 对比synchronized,synchronized使用时会显示的指定一个对象(方法为调用对象,代码块会需要对象作为参数),来获取一个对象的独占锁 而ReentrantLock可能就是使用 ...

  5. Hapi+MySql项目实战配置插件-加载文件渲染母版(三)

    加载插件 一般在其它node框架下,我们安装好插件直接require('插件')就能正常使用了,但是在Hapi下我们必须要Server.register()方法,才能正常使用插件.举个例子: serv ...

  6. 排查 Kubernetes HPA 通过 Prometheus 获取不到 http_requests 指标的问题

    部署好了 kube-prometheus 与 k8s-prometheus-adapter (详见之前的博文 k8s 安装 prometheus 过程记录),使用下面的配置文件部署 HPA(Horiz ...

  7. 「Kafka」Kafka中offset偏移量提交

    在消费Kafka中分区的数据时,我们需要跟踪哪些消息是读取过的.哪些是没有读取过的.这是读取消息不丢失的关键所在. Kafka是通过offset顺序读取事件的.如果一个消费者退出,再重启的时候,它知道 ...

  8. mysql 主主备份

    1.1.主主备份原理. 主主备份实际上是互为主从,主要是为了去缓解写入压力. 1.2.环境准备 两台机器ip分别为 100.100.100.105 (主1) 100.100.100.106(主2) 安 ...

  9. 通过Performance Monitor观察程序内存使用情况

    在学习C# 数据类型和内存等知识点时,看到利用Windows系统下的Performance Monitor-性能监测工具查看程序内存的使用情况.使用过程中遇到个别小问题,现在把观察程序内存的操作步骤简 ...

  10. #《Essential C++》读书笔记# 第一章 C++ 编程基础

    前言 Stanley B.Lippman 先生所著的<C++ Primer>是学习C++的一本非常优秀的教科书,但<C++ Primer>作为一本大部头书,显然不适合所有的初学 ...