@description@

一个随机数发生器会生成 N 种数。

第 i 种数有参数 Ai,记 SA = ∑Ai,随机数发生器会有 Ai/SA 的概率生成 i。

每个时刻都会生成一个数,直到某时刻对于所有的 i,第 i 种数被生成的次数 >= Bi 停止。

求停止的期望时刻。

Constraints

1 <= Ai,Bi,N,∑Ai, ∑Bi <= 400。

Input

输入形式如下:

N

A0 B0

A1 B1



AN−1 BN−1

Output

输出期望时刻 mod 998244353。

Sample Input 1

2

1 1

1 1

Sample Output 1

3

@solution - 1@

先对问题进行初步的转化:

假如在第 t 时刻停止,贡献为 t。

我们可以将 t 的贡献看成第 0 时刻没有停止贡献 1,第 1 时刻没有停止贡献 1,…,第 t-1 时刻没有停止贡献 1,总共贡献 t。

记 p(i) 表示第 i 时刻依然没有停止的概率,则有停止的期望时刻为 \(\sum_{i=0}p(i)\)。

考虑怎么求 p(i)。

假如给定一个生成的序列 x1, x2, …, xi 表示第 j 时刻生成 xj,则得到该序列的概率应为 A[x1]/SA*A[x2]/SA*…*A[xi]/SA。

一种思路是对于所有长度为 i 的未停止序列计算概率之和,但不好做(但可以做)。

我们逆向思维,用 1 – 已停止序列的概率之和,从而得到 p(i)。

记 d[k] 表示 k 已经出现了 d[k] 次。已停止序列即所有的 1 <= k <= n 都满足 d[k] >= B[k]。

记 q[i] 表示已停止序列对应的概率,则有:

\[q[i] = \sum_{d[j] \ge B[j]}^{(\sum_{i=1}^{n}d[j])=i}\frac{i!}{\prod_{j=1}^{n}(d[j]!)}*\prod_{j=1}^{n}(\frac{A[j]}{SA})^{d[j]}
\]

注意到这个式子里面含有卷积,而且还以阶乘为分母。我们考虑将其改写成指数型生成函数的形式。

记 Q(x) 为 q 的指数型生成函数,则有:

\[Q(x) = \prod_{i=1}^{n}(\sum_{j=B[i]}\frac{(\frac{A[j]}{SA}x)^j}{j!})\\
=\prod_{i=1}^{n}(e^{\frac{A[j]}{SA}x}-\sum_{j=0}^{B[i]-1}\frac{(\frac{A[j]}{SA}x)^j}{j!})\]

设 P(x) 表示 p 的指数型生成函数,得到:

\[P(x) = e^x - Q(x)\\
=e^x - \prod_{i=1}^{n}(e^{\frac{A[j]}{SA}x}-\sum_{j=0}^{B[i]-1}\frac{(\frac{A[j]}{SA}x)^j}{j!})\]

这玩意儿可以暴力 O((∑B)^2*∑A) 展开。

展开后每一项长成 \(c_{i, j}e^{\frac{i}{SA}x}x^{j}\) 的形式,其中 i, j 满足 0 <= i <= ∑A, 0 <= j <= ∑B。

我们枚举 i, j,然后算 \(c_{i, j}e^{\frac{i}{SA}x}x^{j}\) 对答案的贡献。

记 t = i/SA。现暂且不考虑 \(c_{i, j}\),最后再乘。将 \(e^{tx}x^{j}\) 展开得到:

\[e^{tx}x^j=\sum_{i=0}\frac{t^ix^{i+j}}{i!}
\]

因为 \(x^{i+j}\) 对应的系数为 p[i+j]/(i+j)!,所以反过来求 p[i+j] 时需要乘 (i+j)!。因此贡献为:

\[S(j) = \sum_{i=0}t^i(i+j)^{\underline{j}}
\]

怎么求 S(j) 呢?利用下降幂的性质 \((i+1)^{\underline{j}} - i^{\underline{j}} = j*i^{\underline{j-1}}\),以及推导等比数列求和的过程,得到:

\[S(j) = \sum_{i=0}t^i(i+j)^{\underline{j}}\\
t*S(j) = \sum_{i=1}t^i(i+j-1)^{\underline{j}}\\
(1-t)*S(j) = j! + j*\sum_{i=1}t^i(i+j-1)^{\underline{j-1}} = j*S(j-1)
\]

因此得到 \(S(j) = \frac{j}{1-t}S(j-1)\)。

又因 j = 0 时就是等比数列求和,即 \(S(0) = \frac{1}{1-t}\),所以 \(S(j) = (\frac{1}{1-t})^{j+1}*j!\)。

总时间复杂度 O((∑B)^2*∑A)。

@accepted code - 1@

#include<cstdio>
const int MAXN = 400;
const int MOD = 998244353;
int inv[MAXN + 5];
struct mint{
int x;
mint(int _x=0) : x(_x) {}
friend mint operator + (const mint &a, const mint &b) {return a.x + b.x >= MOD ? a.x + b.x - MOD : a.x + b.x;}
friend mint operator - (const mint &a, const mint &b) {return a.x - b.x < 0 ? a.x - b.x + MOD : a.x - b.x;}
friend mint operator * (const mint &a, const mint &b) {return 1LL * a.x * b.x % MOD;}
friend mint operator / (const mint &a, const int &b) {return a * inv[b];}
};
mint pow_mod(mint b, int p) {
mint ret = 1;
while( p ) {
if( p & 1 ) ret = ret*b;
b = b*b;
p >>= 1;
}
return ret;
}
void init() {
inv[1] = 1;
for(int i=2;i<=MAXN;i++)
inv[i] = MOD - 1LL*inv[MOD%i]*(MOD/i)%MOD;
}
mint coef[MAXN + 5][MAXN + 5];
int A[MAXN + 5], B[MAXN + 5], N, SA, SB;
void read() {
scanf("%d", &N);
for(int i=0;i<N;i++)
scanf("%d%d", &A[i], &B[i]), SA += A[i], SB += B[i];
}
mint tmp[MAXN + 5][MAXN + 5];
void get() {
coef[0][0] = 1;
for(int i=0;i<N;i++) {
for(int j=0;j<=SA;j++)
for(int k=0;k<=SB;k++)
tmp[j][k] = coef[j][k], coef[j][k] = 0;
mint p = mint(A[i]) / SA, f = MOD - 1;
for(int l=0;l<B[i];l++,f=f/l*p)
for(int j=0;j<=SA;j++)
for(int k=l;k<=SB;k++)
coef[j][k] = coef[j][k] + f*tmp[j][k-l];
for(int j=A[i];j<=SA;j++)
for(int k=0;k<=SB;k++)
coef[j][k] = coef[j][k] + tmp[j-A[i]][k];
}
for(int i=0;i<=SA;i++)
for(int j=0;j<=SB;j++)
coef[i][j] = 0 - coef[i][j];
coef[SA][0] = coef[SA][0] + 1;
}
/*
let t = e^(x/S)
t^S - (t^Ai - (x*Ai/S)^j/j!)
*/
int solve() {
mint ret = 0, f = 1;
for(int j=0;j<=SB;j++,f=f*j)
for(int i=0;i<=SA;i++) {
mint p = mint(i) / SA;
p = pow_mod(1 - p, MOD - 2 - j);
ret = ret + coef[i][j]*p*f;
}
return ret.x;
}
int main() {
init(), read(), get();
printf("%d\n", solve());
}

@solution - 2@

这道题会很容易令人想起 uoj - 449 那道题。

我们尝试使用 min-max 容斥能否解决。

对于某一集合 S = {x1, x2, ..., xm},我们想要求它最早达到 Bi 的限制的期望时刻。

还是转化一下问题,求第 t 时刻没有任何元素达到 Bi 的概率 p(t),将 p(t) 求和即是期望。

因此,这个集合的贡献如下所示:

\[(-1)^{m+1}*\frac{SA}{\sum A[xi]}*\sum_{0\le di < B[xi]}\frac{(\sum di)!}{\prod(di!)}*\prod(\frac{A[xi]}{\sum A[xi]})^{di}
\]

前面的 \((-1)^{m+1}\) 为容斥系数,\(\frac{SA}{\sum A[xi]}\) 为在集合内抽中一个数的期望。

显然我们不能枚举每个集合然后算。考虑往集合内加入一个元素 y,贡献会怎么变:

\[(-1)^{m+2}*\frac{SA}{A[y] + \sum A[xi]}*\sum_{0\le di < B[xi]}\sum_{0\le dy < B[y]}\frac{(dy + \sum di)!}{dy!*\prod(di!)}*\prod(\frac{A[xi]}{A[y] + \sum A[xi]})^{di}*(\frac{A[y]}{A[y] + \sum A[xi]})^{dy}
\]

通过观察式子,假如我们限制以前的集合中 \(\sum A[xi] = p\),\(\sum di = q\);并在加入 y 的时候枚举 dy,则贡献是不受其他条件影响的。

记 f[i][p][q] 表示已经考虑了 n 个数中的前 i 个数,当前集合 \(\sum A[xi] = p, \sum di = q\),所有与 p, q 无关的值的乘积之和。

与 p, q 无关的值实际上就是 \((-1)*\frac{A[xi]^{di}}{di!}\),转移时乘一下这个即可。

最后再把 f[n][p][q] 拿出来算贡献即可。

总共转移不超过 O(∑Bi) 次,时间复杂度为 O((∑Bi)^2*Ai)。

@accepted code - 2@

#include<cstdio>
const int MOD = 998244353;
const int MAXN = 400;
int inv[MAXN + 5];
void init() {
inv[1] = 1;
for(int i=2;i<=MAXN;i++)
inv[i] = MOD - 1LL*inv[MOD%i]*(MOD/i)%MOD;
}
struct modint{
int x;
modint(int _x=0):x(_x) {}
friend modint operator + (modint x, modint y) {return (x.x + y.x) >= MOD ? x.x + y.x - MOD : x.x + y.x;}
friend modint operator - (modint x, modint y) {return (x.x - y.x) < 0 ? x.x - y.x + MOD : x.x - y.x;}
friend modint operator * (modint x, modint y) {return 1LL*x.x*y.x%MOD;}
friend modint operator / (modint x, int k) {return x*inv[k];}
};
modint pow_mod(modint b, int p) {
modint ret = 1;
while( p ) {
if( p & 1 ) ret = ret*b;
b = b*b;
p >>= 1;
}
return ret;
}
modint f[2][MAXN + 5][MAXN + 5];
int A[MAXN + 5], B[MAXN + 5], SA, SB;
int main() {
init();
int n; scanf("%d", &n);
for(int i=0;i<n;i++)
scanf("%d%d", &A[i], &B[i]), SA += A[i], SB += B[i];
f[0][0][0] = MOD - 1;
for(int i=0;i<n;i++) {
for(int j=0;j<=SA;j++)
for(int k=0;k<=SB;k++)
f[1][j][k] = f[0][j][k];
modint p = 1;
for(int l=0;l<B[i];l++,p=p*A[i]/l)
for(int j=A[i];j<=SA;j++)
for(int k=l;k<=SB;k++)
f[0][j][k] = f[0][j][k] - f[1][j-A[i]][k-l]*p;
}
modint ans = 0;
for(int j=1;j<=SA;j++) {
modint p = 1, q = modint(SA)/j;
for(int k=0;k<=SB;k++,p=p*k/j)
ans = ans + f[0][j][k]*p*q;
}
printf("%d\n", ans.x);
}

@details@

主要是式子的推导,其实代码实现本身没有太大难度。

这个题涉及了好多组合数学以及期望概率的套路。

@atcoder - AGC038E@ Gachapon的更多相关文章

  1. Atcoder Grand Contest 038 E - Gachapon(Min-Max 容斥+背包)

    Atcoder 题面传送门 & 洛谷题面传送门 我竟然能独立做出 Ag 的 AGC E,incredible!更新了 Atcoder 做题难度上限( 首先按照套路 Min-Max 容斥,\(a ...

  2. AtCoder Grand Contest 038E - Gachapon

    \(\bf Description\) 一个 \(0\) 到 \(n-1\) 的随机数生成器,生成 \(i\) 的概率是 \(A_i/S\) ,其中 \(S=\sum_{i=0}^{n} A_i\) ...

  3. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  4. AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识

    链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...

  5. AtCoder Regular Contest 082

    我都出了F了……结果并没有出E……atcoder让我差4分上橙是啥意思啊…… C - Together 题意:把每个数加1或减1或不变求最大众数. #include<cstdio> #in ...

  6. AtCoder Regular Contest 069 D

    D - Menagerie Time limit : 2sec / Memory limit : 256MB Score : 500 points Problem Statement Snuke, w ...

  7. AtCoder Regular Contest 076

    在湖蓝跟衡水大佬们打的第二场atcoder,不知不觉一星期都过去了. 任意门 C - Reconciled? 题意:n只猫,m只狗排队,猫与猫之间,狗与狗之间是不同的,同种动物不能相邻排,问有多少种方 ...

  8. AtCoder Grand Contest 016

    在雅礼和衡水的dalao们打了一场atcoder 然而窝好菜啊…… A - Shrinking 题意:定义一次操作为将长度为n的字符串变成长度n-1的字符串,且变化后第i个字母为变化前第i 或 i+1 ...

  9. AtCoder Beginner Contest 069【A,水,B,水,C,数学,D,暴力】

    A - K-City Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement In K-city, ...

随机推荐

  1. zoj 1001 python起步

    /*赶角还是挺好的....*/ import sys for line in sys.stdin: a=line.split() print int(a[0])+int(a[1])

  2. Spring Bean 作用域

    Bean 的作用域 当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项.例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean ...

  3. springmvc 使用poi解析excel并通过hibernate连续插入多条数据 实际数据库只能保存最后一条

    有一个原始数据的excel表 用poi解析之后通过hibernate插数据库 结果 后来发现,有人说 果断尝试 问题解决 但是这好像并不是真正解决问题,只是解决了一个现象 因为有人说 https:// ...

  4. 易语言连接RCON详细教程实例(演示连接Unturned服务器RCON)

    一.准备工作 工 具: 1.易语言 2.RCON服务端(这里我使用unturned服务器的RCON作为演示) 二.启动Unturned服务器并配置RCON 打开unturned服务器路径:F:\Unt ...

  5. js创建svg元素的方法

    需要JQuery <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  6. 【同余最短路】洛谷 P2662 牛场围栏

    关于同余最短路的部分 [同余最短路]P3403跳楼机/P2371墨墨的等式 [P2662牛场围栏] 题目背景 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕 ...

  7. python实例 字符串

    比起C/C++,Python处理字符串的方式实在太让人感动了.把字符串当列表来用吧. #! /usr/bin/python word="abcdefg" a=word[2] pri ...

  8. SVN failed: 405 Method Not Allowed

    SVN update 时,错误:PROPFIND request on '/svn/xxxx' failed: 405 Method Not Allowed. 解决办法如下: 第一步:查看SVN服务器 ...

  9. python 爬取段子网段子写入文件

    import requests import re 进入网址 for i in range(1,5): page_url = requests.get(f"http://duanziwang ...

  10. 重温 Webpack, Babel 和 React

    开始之前 在书写文章之前,我假设大家已经有了 JavaScript,Node 包管理工具,Linux 终端操作 这些基本技能,接下来,我将一步一步指引大家从头搭建一个 React 项目 最终实现的效果 ...