首先,题目中的过程可以看作:每次选择任意一个燃料仓,给它装填 \(1\) 单位的燃料,如果此时恰好 “填满” 了它,就给答案 \(+1\)。

考虑 \(n\) 号燃料仓填满的概率,因为所有燃料仓是等价的,由期望线性性,答案就是这个概率乘 \(n\)。

填满 \(n\) 号燃料仓前,我们必定给它装填了 \(1\) 单位。考虑这之前的状态:前 \(n - 1\) 个燃料仓中至少有一个装填了少于 \(b\) 单位,第 \(n\) 个燃料仓恰好装填了 \(a - 1\) 单位。所以说,\(n\) 号仓被填满概率就是:

\[\frac{1}{n} \sum_{\min\{x_1, x_2, \cdots, x_{n - 1}\} < b, x_n = a - 1} \left(\frac{1}{n}\right)^{\sum_{i = 1}^{n} x_i} \binom{\sum_{i = 1}^{n} x_i}{x_1, x_2, \cdots, x_n}
\]

可以把 \([\min\{x_1, x_2, \cdots, x_{n - 1}\} < b]\) 转化成 \(1 - [x_1, x_2, \cdots, x_{n - 1} \ge b]\)。考虑写成 EGF 的形式:

\[\hat{f}(x) = \frac{1}{n} \left(\left(e^{\frac{1}{n}x} \right)^{n - 1} - \left(e^{\frac{1}{n}x} - \sum_{i = 0}^{b - 1} \frac{\left(\frac{1}{n}\right)^ix^i}{i!}\right)^{n - 1}\right)\frac{\left(\frac{1}{n}\right)^{a - 1} x^{a - 1}}{(a - 1)!}
\]

我们要求的即是 \(\sum_{i \ge 0} \hat{f}_i \cdot i!\)。

考虑换元,令 \(u = e^{\frac{1}{n}x}, v = (\frac{x}{n})\),那么有:

\[\hat{f}(x) = \frac{1}{n}\left(u^{n - 1} - \left(u - \sum_{i = 0}^{b - 1} \frac{v^i}{i!}\right)^{n - 1}\right)\frac{v^{a - 1}}{(a - 1)!}
\]

先假设 \(\hat{f}(x) = \sum f_{p, q} u^p v^q\),我们对每一项分别考虑:

\[\begin{split}
& u^pv^q \\
= & e^{\frac{p}{n}x} \left(\frac{1}{n}\right)^q x^q \\
= & \left(\frac{1}{n}\right)^q \sum_{i \ge 0} \frac{\left(\frac{p}{n}\right)^ix^{i + q}}{i!}
\end{split}
\]

这一项对答案的贡献是:

\[\begin{split}
& f_{p, q}\sum_{i \ge 0}i![x^i]u^pv^q \\
= & f_{p, q} \left(\frac{1}{n}\right)^q \sum_{i \ge 0} \frac{\left(\frac{p}{n}\right)^i(i + q)!}{i!} \\
= & f_{p, q} \left(\frac{1}{n}\right)^q q! \sum_{i \ge 0} \left(\frac{p}{n}\right)^i \binom{i + q}{i} \\
= & f_{p, q} \left(\frac{1}{n}\right)^q q! \frac{1}{\left(1 - \frac{p}{n}\right)^{q + 1}} \\
\end{split}
\]

所以,我们已经可以快速求 \(f_{p, q} u^p v^q\) 对答案的贡献了,现在考虑如何求 \(f_{p, q}\)。

令 \(\sum_{i = 0}^{b - 1} \frac{v^i}{i!} = P\),\(P\) 是关于 \(v\) 的 \(b - 1\) 次多项式。二项式定理展开,我们有:

\[\begin{split}
\hat{f}(x) & = \frac{1}{n}\left(u^{n - 1} - \left(u - \sum_{i = 0}^{b - 1} \frac{v^i}{i!}\right)^{n - 1}\right)\frac{v^{a - 1}}{(a - 1)!} \\
& = \frac{1}{n(a - 1)!}\left(u^{n - 1} - \sum_{i = 0}^{n - 1} \binom{n - 1}{i} \left(-1\right)^{i}u^{n - 1 - i} P^i \right)v^{a - 1} \\
& = \frac{1}{n(a - 1)!}\left(\sum_{i = 1}^{n - 1} \binom{n - 1}{i} \left(-1\right)^{i - 1}u^{n - 1 - i} P^i \right)v^{a - 1} \\
\end{split}
\]

我们只要算出 \(P^1, P^2, \cdots, P^{n - 1}\) 的各项系数即可。

暴力算是 \(O(n^2b^2)\) 的,可以用 FFT 优化到 \(O(n^2b \log nb)\),下面讲一个 \(O(n^2b)\) 的方法。

发现 \(P' = P - \frac{v^{b - 1}}{(b - 1)!}\),考虑微分方程:

\[\begin{split}
(P^k)' & = kP' P^{k - 1} \\
& = k(P - \frac{v^{b - 1}}{(b - 1)!})P^{k - 1}\\
& = k(P^k - Q)\\
\end{split}
\]

其中 \(Q\) 是 \(P^{k - 1}\) 乘上一个单项式。我们按照 \(k\) 从小到大的顺序递推,假设我们已经求出了当前的 \(Q\)。设 \(P^k = \sum_{i = 0}^{m} p_iv^i, Q = \sum_{i = 0}^{m} q_iv^i\),那么:

\[\sum_{i = 0}^{m - 1} (i + 1)p_{i + 1}v^i = k\left(\sum_{i = 0}^{m} p_iv^i - \sum_{i = 0}^{m} q_iv^i\right) \\
p_{i + 1} = \frac{k(p_i - q_i)}{i + 1}
\]

我们还有 \(p_0 = 1\),所以就可以直接递推了。总共的时间复杂度为 \(O(n^2b)\)。

#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= int(b); i++)
#define per(i, a, b) for (int i = (a); i >= int(b); i--)
using namespace std; const int maxn = 250, maxm = maxn * maxn, mod = 998244353;
int n, a, b, fact[maxm + 3], finv[maxm + 3], inv[maxm + 3], m, p[maxm + 3], q[maxm + 3]; int qpow(int a, int b) {
int c = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod) if (b & 1) c = 1ll * a * c % mod;
return c;
} void prework(int n) {
fact[0] = 1;
rep(i, 1, n) fact[i] = 1ll * fact[i - 1] * i % mod;
finv[n] = qpow(fact[n], mod - 2);
per(i, n, 1) finv[i - 1] = 1ll * finv[i] * i % mod;
rep(i, 1, n) inv[i] = 1ll * fact[i - 1] * finv[i] % mod;
} int C(int n, int m) {
return 1ll * fact[n] * finv[m] % mod * finv[n - m] % mod;
} int main() {
scanf("%d %d %d", &n, &a, &b);
prework(max(a, n * b));
p[0] = 1;
int res = 0;
rep(k, 1, n - 1) {
rep(i, 0, m) q[i + b - 1] = 1ll * p[i] * finv[b - 1] % mod;
m += b - 1;
rep(i, 0, m - 1) p[i + 1] = 1ll * inv[i + 1] * k % mod * (p[i] - q[i] + mod) % mod;
int num = qpow((1 - 1ll * (n - 1 - k) * inv[n] % mod + mod) % mod, mod - 2);
int cur = 1ll * (k & 1 ? 1 : mod - 1) * C(n - 1, k) % mod * qpow(1ll * inv[n] * num % mod, a - 1) % mod * fact[a - 1] % mod;
rep(i, 0, m) {
cur = 1ll * cur * (i == 0 ? 1 : inv[n]) % mod * (i == 0 ? 1 : i + a - 1) % mod * num % mod;
res = (res + 1ll * p[i] * cur) % mod;
}
}
res = 1ll * res * finv[a - 1] % mod;
printf("%d\n", res);
return 0;
}

「UOJ 514」通用测评号(生成函数)的更多相关文章

  1. 「UOJ#117」 欧拉回路

    欧拉回路 - 题目 - Universal Online Judge 题意: 给定有向图或无向图,求一条欧拉回路. 题解 心路历程:woc什么傻哔东西->哇真香我的吗!(逃 首先我知道很多人把欧 ...

  2. Solution -「UNR #5」「UOJ #671」诡异操作

    \(\mathcal{Desciprtion}\)   Link.   给定序列 \(\{a_n\}\),支持 \(q\) 次操作: 给定 \(l,r,v\),\(\forall i\in[l,r], ...

  3. Solution -「UOJ #46」玄学

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\) 和 \(q\) 次操作,操作内容如下: 给出 \(l,r,k,b\),声明一个修改方案,表示 ...

  4. Solution -「JOISC 2020」「UOJ #509」迷路的猫

    \(\mathcal{Decription}\)   Link.   这是一道通信题.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图与两个限制 \(A,B\).   程序 Anthon ...

  5. Solution -「UR #21」「UOJ #632」挑战最大团

    \(\mathcal{Description}\)   Link.   对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...

  6. Solution -「UOJ #87」mx 的仙人掌

    \(\mathcal{Description}\)   Link.   给出含 \(n\) 个结点 \(m\) 条边的仙人掌图.\(q\) 次询问,每次询问给出一个点集 \(S\),求 \(S\) 内 ...

  7. Solution -「UR #2」「UOJ #32」跳蚤公路

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的带权有向图,每条边还有属性 \(s\in\{-1,0,1\}\).对于每个 \(u ...

  8. Solution -「UOJ #450」复读机

    \(\mathcal{Description}\)   Link.   求从 \(m\) 种颜色,每种颜色无限多的小球里选 \(n\) 个构成排列,使得每种颜色出现次数为 \(d\) 的倍数的排列方案 ...

  9. Diary / Solution Set -「WC 2022」线上冬眠做噩梦

      大概只有比较有意思又不过分超出能力范围的题叭.   可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics   任意一个 ...

随机推荐

  1. MHA 高可用介绍

    目录 MHA 介绍 MHA 简介(Master High Availability) MHA 工作原理(转载) MHA 架构 MHA 工具 Manager 节点 Node 节点 MHA 优点 MHA ...

  2. pyhook的简单使用

    实验内容: 通过python编程调用windows的api,编写键盘和鼠标监控的hook,将相关信息保存记录到txt文档中. 实验步骤: 1.Hook技术,pyHook3和pywin32简介 1.1  ...

  3. 蓝桥杯-摔手机问题【dp】

    非常详细的题解:戳这里 例题:poj-3783 Balls Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 115 ...

  4. 关于虚继承的sizeof问题

    首先关于虚继承和普通继承的知识,我总结一下: 1.普通继承时,无论派生类是否定义新的虚函数,基类和派生类总是共享一个虚函数表,不需要另加指向虚函数的指针,派生类只是将虚函数表中的元素改成了派生类的地址 ...

  5. μC/OS-III---I笔记12---任务管理

    任务管理任务切换应该算是UCOS最基本的部分,首先保存当前任务寄存器的内容到当前任务的堆栈:接着弹出即将进行的任务的堆栈内容到寄存器中然后就是按寄存器内容执行,这个过程成为上下文切换.任务堆栈在创建任 ...

  6. Spring配置声明式事务

    Spring的事务有两种配置,一种是编程式,另一种是声明式,这里我们配置的是声明式事务 <?xml version="1.0" encoding="UTF-8&qu ...

  7. Dapr 正式发布1.0

    年前我写了一篇博客<Dapr 已在塔架就位 将发射新一代微服务>, 今天Dapr 正式发布了1.0 : Dapr Runtime v1.0.0 Dapr dotnet SDK v1.0.0 ...

  8. LeetCode 数组分割

    LeetCode 数组分割 LeetCode 数组怎么分割可以得到左右最大值的差值的最大 https://www.nowcoder.com/study/live/489/1/1 左右最值最大差 htt ...

  9. js 实现各种数据结构 APP

    js 实现各种数据结构 APP 常见数据结构: 数组,队列,栈,堆,链表,集合,字典,散列表,树, 图 Array, Queue, Link, Collection, Set,Map, HashMap ...

  10. how to export svg form web page in js

    how to export svg form web page in js https://stackoverflow.com/questions/2483919/how-to-save-svg-ca ...