「SOL」射命丸文的笔记 (洛谷)
讲题人:“这是一个很经典的模型,大家应该都会”
我:“???”
# 题面
给出 \(m\),求所有 \(m\) 个点的有标号强联通竞赛图的哈密顿回路数量的平均数。答案对 \(998244353\) 取模。
输入 \(n\),对每个 \(m=1\sim n\) 求解。
数据规模:\(n\le10^5\)。
# 解析
问题分成两个部分:
- 所有 \(m\) 个点的竞赛图的哈密顿回路数量;注意到只有强联通的竞赛图有哈密顿回路,所以计算时不用管强联通;
- \(m\) 个点的强联通竞赛图数量。
第一个部分。我们发现对一个竞赛图计算它的哈密顿回路没法做,考虑对一个哈密顿回路计算它出现在多少个竞赛图中。
哈密顿回路从 \(1\) 处断开,就是一个从 \(1\) 开头的 \(1\sim m\) 的排列,数量为 \((m-1)!\)。我们钦定这样一条哈密顿回路在竞赛图上,相当于已经给 \(m\) 条边钦定了方向,剩下的 \(\frac{m(m-1)}2-m\) 条边随便定向,即哈密顿回路总数为:
\]
特判一下 \(n\le2\)。
第二个部分。记 \(f_i\) 表示 \(i\) 个点的强联通竞赛图的数量,我们要计算 \(f_1\sim f_n\)。计算这些值,可以考虑生成函数 —— 注意到有标号,记 \(f_i\) 的 EGF 为 \(F(x)\)。
直接限制强联通并不好算,于是正难则反。计算一定没有强联通的竞赛图的数量。
重要性质
将竞赛图强联通缩点后的图记为 \(T\),对 \(T\) 做拓扑排序,则按拓扑序排列的点在 \(T\) 上形成一条链。
如果竞赛图不是强联通,则一定存在多个强联通分量,结合上述性质,可以找到拓扑序最小的一个强联通分量 \(G_1\),而剩下的图 \(G_2\) 是一个任意的竞赛图。由于 \(G_1\) 是极大的强联通分量,且拓扑序最小,则 \(G_1\) 和 \(G_2\) 之间的所有边都是从 \(G_1\) 连向 \(G_2\)。
我们可以枚举 \(G_1\) 的大小为 \(i\),则 \(G_1\) 是大小为 \(i\) 的强联通竞赛图,而 \(G_2\) 为大小为 \(m-i\) 的任意竞赛图。记 \(g_i\) 为 \(i\) 个点的任意竞赛图数量。可以写出转移式:
\]
有组合数,能够拆成 EGF 的形式。记 \(G(x)\) 为 \(g_i\) 的 EGF:
\frac{f_s}{s!}=\frac{g_s}{s!}-\sum_{i=1}^{s-1}\frac{f_i}{i!}\times\frac{g_{s-i}}{(s-i)!}\\
F(x)=G(x)-F(x)G(x)
\end{aligned}
\]
分治 NTT 或者多项式求逆,但是感觉多项式求逆好写些……
# 源代码
/*Lucky_Glass*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD = 998244353, N = 1e5 + 10, L = 262144;
#define con(typ) const typ &
inline int add(int a, con(int) b) {
return (a += b) >= MOD ? a - MOD : a;
}
inline int sub(int a, con(int) b) {
return (a -= b) < 0 ? a + MOD : a;
}
inline int mul(con(int) a, con(int) b) {
return int(1ll * a * b % MOD);
}
inline int iPow(int a, int b) {
int r = 1;
while ( b ) {
if ( b & 1 ) r = mul(a, r);
a = mul(a, a), b >>= 1;
}
return r;
}
namespace BASICPOLY {
int rev[L + 10], elg2[L + 10], powg[L + 10];
void init() {
elg2[1] = 0, powg[0] = 1, powg[1] = iPow(3, (MOD - 1) >> 18);
for (int i = 2; i <= L; i++) {
elg2[i] = elg2[(i + 1) >> 1] + 1;
powg[i] = mul(powg[i - 1], powg[1]);
}
}
void ntt(int *arr, con(int) len, con(int) typ) {
for (int i = 1; i < len; i++) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (len >> 1) : 0);
if ( i < rev[i] ) swap(arr[i], arr[rev[i]]);
}
for (int i = 1, ii = 2; i < len; i <<= 1, ii <<= 1) {
int s = L >> elg2[ii];
for (int j = 0; j < len; j += ii) {
int *a = arr + j, *b = a + i, *p = powg, q = *b;
for (int k = 0; k < i; k++, a++, q = mul(*(p += s), *(++b)))
*b = sub(*a, q), *a = add(*a, q);
}
}
if ( typ == -1 ) {
reverse(arr + 1, arr + len);
int ivn = MOD - ((MOD - 1) >> elg2[len]);
if ( mul(ivn, len) != 1 ) printf("???");
for (int i = 0; i < len; i++) arr[i] = mul(arr[i], ivn);
}
}
int ta[L + 10], tb[L + 10];
void polyMul(int *a, int *b, con(int) la, con(int) lb, int *r,
con(int) fr = -1) {
int lr = la + lb - 1, len = 1 << elg2[lr];
for (int i = 0; i < la; i++) ta[i] = a[i];
for (int i = la; i < len; i++) ta[i] = 0;
for (int i = 0; i < lb; i++) tb[i] = b[i];
for (int i = lb; i < len; i++) tb[i] = 0;
ntt(ta, len, 1), ntt(tb, len, 1);
for (int i = 0; i < len; i++) ta[i] = mul(ta[i], tb[i]);
ntt(ta, len, -1);
for (int i = 0, ii = ~fr ? fr : lr; i < ii; i++) r[i] = ta[i];
}
void polyInv(int *a, int *r, con(int) len) {
if ( len == 1 ) {
r[0] = iPow(a[0], MOD - 2);
return;
}
polyInv(a, r, (len + 1) >> 1);
int llen = 1 << elg2[len << 1];
for (int i = 0; i < len; i++) ta[i] = a[i];
for (int i = len; i < llen; i++) ta[i] = 0;
for (int i = 0, ii = (len + 1) >> 1; i < ii; i++) tb[i] = r[i];
for (int i = (len + 1) >> 1; i < llen; i++) tb[i] = 0;
ntt(ta, llen, 1), ntt(tb, llen, 1);
for (int i = 0; i < llen; i++)
ta[i] = mul(tb[i], sub(2, mul(ta[i], tb[i])));
ntt(ta, llen, -1);
for (int i = 0; i < len; i++) r[i] = ta[i];
}
}
int fac[N], ifac[N], ara[N], arb[N];
int calc(con(int) n) {
if ( n <= 2 ) return n == 1;
return mul(fac[n - 1], iPow(2, (n * (n - 1ll) / 2 - n) % (MOD - 1)));
}
int funS(con(int) n) {
return iPow(2, n * (n - 1ll) / 2 % (MOD - 1));
}
void init() {
fac[0] = 1;
for (int i = 1; i < N; i++)
fac[i] = mul(fac[i - 1], i);
ifac[N - 1] = iPow(fac[N - 1], MOD - 2);
for (int i = N - 2; ~i; i--)
ifac[i] = mul(ifac[i + 1], i + 1);
BASICPOLY::init();
for (int i = 1; i < N; i++) ara[i] = mul(funS(i), ifac[i]);
ara[0]++;
BASICPOLY::polyInv(ara, arb, N);
ara[0]--;
BASICPOLY::polyMul(ara, arb, N, N, ara, N);
for (int i = 1; i < N; i++) ara[i] = mul(ara[i], fac[i]);
}
int main() {
init();
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
if ( ara[i] )
printf("%d\n", mul(calc(i), iPow(ara[i], MOD - 2)));
else printf("-1\n");
}
return 0;
}
THE END
Thanks for reading!
你喜欢海风咸咸的气息
踩着湿湿的沙砾
你说人们的骨灰应该撒进海里
你问我死后会去哪里
有没有人爱你
世界能否不再
——《海底(Cover)》 By 祖娅纳惜
「SOL」射命丸文的笔记 (洛谷)的更多相关文章
- loj2734「JOISC 2016 Day 2」女装大佬 || 洛谷P3615 如厕计划
loj2734 洛谷P3615 http://218.5.5.242:9021/problem/185 不会做... 题解(来自ditoly): 这一步更详细的解释(来自kkksc03): 还是从后面 ...
- 斜率优化dp学习笔记 洛谷P3915[HNOI2008]玩具装箱toy
本文为原创??? 作者写这篇文章的时候刚刚初一毕业…… 如有错误请各位大佬指正 从例题入手 洛谷P3915[HNOI2008]玩具装箱toy Step0:读题 Q:暴力? 如果您学习过dp 不难推出d ...
- 边带权并查集 学习笔记 & 洛谷P1196 [NOI2002] 银河英雄传说 题解
花了2h总算把边带权并查集整明白了qaq 1.边带权并查集的用途 众所周知,并查集擅长维护与可传递关系有关的信息.然而我们有时会发现并查集所维护的信息不够用,这时"边带权并查集"就 ...
- 解题笔记-洛谷-P1010 幂次方
0 题面 题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+ ...
- 快速沃尔什变换(FWT)学习笔记 + 洛谷P4717 [模板]
FWT求解的是一类问题:\( a[i] = \sum\limits_{j\bigoplus k=i}^{} b[j]*c[k] \) 其中,\( \bigoplus \) 可以是 or,and,xor ...
- [折腾笔记] 洛谷P1149-火柴棒等式 AC记
原题链接: https://www.luogu.org/problem/P1149 题面简述: 给你n根火柴棍,你可以拼出多少个形如"A+B=C""A+B=C" ...
- STL Queue(队列)学习笔记 + 洛谷 P1540 机器翻译
队(Queue) 队简单来说就是一个先进先出的“栈”,但是不同于标准“栈”的先进后出. 基本操作: push(x) 将x压入队列的末端 pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回 ...
- STL Stack(栈)学习笔记 + 洛谷 P1449 后缀表达式
稍微看了看刘汝佳的白皮书,“实用主义”的STL实在是香到我了,而且在实验室大佬的推荐下我开始了stl的学习. 每篇附带一个题目方便理解,那行,直接开始. 毕竟是实用主义,所以就按照给的题目的例子来理解 ...
- 「LGR-049」洛谷7月月赛 D.Beautiful Pair
「LGR-049」洛谷7月月赛 D.Beautiful Pair 题目大意 : 给出长度为 \(n\) 的序列,求满足 \(i \leq j\) 且 $a_i \times a_j \leq \max ...
- 「P4994」「洛谷11月月赛」 终于结束的起点(枚举
题目背景 终于结束的起点终于写下句点终于我们告别终于我们又回到原点…… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演.如果这次 NO ...
随机推荐
- 02.java基础(一)java的基础、方法和数组
目录 Java基础 Java特性 Java程序运行机制 Java基础语法 1.数据类型 基本类型 引用类型 数据类型扩展 String类型内存分配过程 转义字符 类型转换 变量 常量 2.运算符 逻辑 ...
- VS Code第一部分--创建
第一步:Win键+R cmd 打开之后 输入 vue ui 运行结束后 会显示一个仪表盘页面 点击左下方的更多 点击项目管理器 点击创建 输入自己创建的文件夹地址 按回车保存 点击下方的创建 ...
- Tomcat集群配置--负载均衡
Tomcat集群配置学习篇-----分布式应用 现目前基于javaWeb开发的应用系统已经比比皆是,尤其是电子商务网站,要想网站发展壮大,那么必然就得能够承受住庞大的网站访问量:大家知道如果服务器访问 ...
- 排查前端接受后端的map产生的字段错误
报错内容 [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingExce ...
- 地址重写了,只是ip 没转发,应该是9999那个才对,rewrite /sbgl/(.*) http://127.0.0.1:9999/$1 permanent;,这样,
记录想nginx搞路径重写的失败历程. 1.想将从nginx发出的127.0.0.1:80 请求过来的带sbgl的字眼去掉,然后,代理为127.0.0.1:9999, 所以我就百度出这个 这个 r ...
- uml类图中的+,-,#符号的含义
描述类的属性的可见性: UML中,可见性分为4级 1.public 公用的 :用+ 前缀表示 ,该属性对所有类可见 2.protected 受保护的:用 # 前缀表示,对该类的子孙可见 3.priva ...
- Win10家庭版找不到组策略gpedit.msc怎么办
Win10家庭版找不到组策略gpedit.msc怎么办 @echo off pushd "%~dp0" dir /b %systemroot%\Windows\servicing\ ...
- Adobe Acrobat PDF Reader DC软件下载
安装包下载 https://get.adobe.com/en/reader/enterprise/ ftp下载,按日期排序 ftp://ftp.adobe.com/pub/adobe/reader/w ...
- P5731 蛇形方阵
P5731 [深基5.习6]蛇形方阵 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) //为什么用动态二维数组 --->To play to user's input, but ...
- CocosCreator基于jenkins自动构建
1.新建Item,输入名称后选择Freestyle project后点击确定 2.配置项目,自定义工作目录 3.配置源码管理和要摘取的分支 4.构建触发器选择github触发 5.构建选择执行wind ...