暴力就是
Θ
(
n
×
m
)
\Theta(n\times m)
Θ(n×m)
如果
n
,
m
≤
1
0
5
n,m \le 10^5
n,m≤105 ?
考虑问题的转换,设
a
i
a_i
ai 表示
i
i
i 小的在它后面的数的个数
0
≤
a
i
≤
i
−
1
0\le a_i \le i-1
0≤ai≤i−1,显然任何一个满足要求的
a
a
a 数列都可以从大到小放数字构成一个满足要求的排列
那么就是要求
0
≤
a
i
≤
i
−
1
,
∑
i
=
1
n
a
i
=
m
0\le a_i \le i-1,\sum_{i=1}^{n}a_i=m
0≤ai≤i−1,∑i=1nai=m 的方案数
考虑生成函数
∏
i
=
1
n
∑
j
=
0
i
−
1
x
j
\prod_{i=1}^{n}\sum_{j=0}^{i-1}x^j
i=1∏nj=0∑i−1xj
∏
i
=
1
n
1
−
x
i
1
−
x
\prod_{i=1}^{n}\frac{1-x^i}{1-x}
i=1∏n1−x1−xi
方法一
求
L
n
Ln
Ln 后,即
∑
i
=
1
n
L
n
(
1
−
x
i
)
−
n
L
n
(
1
−
x
)
\sum_{i=1}^{n}Ln(1-x^i)-nLn(1-x)
i=1∑nLn(1−xi)−nLn(1−x)
而
L
n
(
1
−
x
i
)
=
−
∑
j
=
1
x
i
j
j
Ln(1-x^i)=-\sum_{j=1}\frac{x^{ij}}{j}
Ln(1−xi)=−j=1∑jxij
证明:
L
n
(
F
(
x
)
)
=
G
(
x
)
Ln(F(x))=G(x)
Ln(F(x))=G(x)
F
′
(
x
)
F
(
x
)
=
G
′
(
x
)
\frac{F'(x)}{F(x)}=G'(x)
F(x)F′(x)=G′(x)
−
i
x
i
−
1
1
−
x
i
=
G
′
(
x
)
\frac{-ix^{i-1}}{1-x^i}=G'(x)
1−xi−ixi−1=G′(x)
∑
j
=
0
−
i
x
i
−
1
x
i
j
=
G
′
(
x
)
\sum_{j=0}-ix^{i-1}x^{ij}=G'(x)
j=0∑−ixi−1xij=G′(x)
∑
j
=
0
−
i
x
i
j
+
i
i
j
+
i
=
G
(
x
)
\sum_{j=0}\frac{-ix^{ij+i}}{ij+i}=G(x)
j=0∑ij+i−ixij+i=G(x)
∑
j
=
1
−
x
i
j
j
\sum_{j=1}\frac{-x^{ij}}{j}
j=1∑j−xij
证毕
以调和级数的复杂度
Θ
(
n
l
n
n
)
\Theta(nlnn)
Θ(nlnn)求出来后
e
x
p
exp
exp 就好了
方法二
∏
i
=
1
n
1
−
x
i
1
−
x
\prod_{i=1}^{n}\frac{1-x^i}{1-x}
i=1∏n1−x1−xi
∏
i
=
1
n
(
1
−
x
i
)
(
1
1
−
x
)
n
\prod_{i=1}^{n}(1-x^i)(\frac{1}{1-x})^n
i=1∏n(1−xi)(1−x1)n
后面的
(
1
1
−
x
)
n
=
(
∑
i
=
0
x
i
)
n
(\frac{1}{1-x})^n=(\sum_{i=0}x^i)^n
(1−x1)n=(i=0∑xi)n
即就是从
n
n
n 个不同的集合中间可以重复的取出
i
i
i 个的方案数的生成函数
那么就是
∑
i
=
0
(
n
−
1
n
+
i
−
1
)
x
i
\sum_{i=0}(^{n+i-1}_{n-1})x^i
i=0∑(n−1n+i−1)xi
考虑前面的
∏
i
=
1
n
(
1
−
x
i
)
\prod_{i=1}^{n}(1-x^i)
i=1∏n(1−xi)
相当于一个带符号的背包计数问题
而第
i
i
i 个的体积是
i
i
i
经典
D
P
DP
DP,就是选出一个上升的序列的方案数
设
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示选了
i
i
i 个,和为
j
j
j 的方案
f
[
i
]
[
j
]
=
f
[
i
]
[
j
−
i
]
−
f
[
i
−
1
]
[
j
−
i
]
f[i][j]=f[i][j-i]-f[i-1][j-i]
f[i][j]=f[i][j−i]−f[i−1][j−i] (带符号)
考虑到可能有某个的大小超过
n
n
n
那么
f
[
i
]
[
j
]
+
=
f
[
i
−
1
]
[
j
−
(
n
+
1
)
]
f[i][j]+=f[i-1][j-(n+1)]
f[i][j]+=f[i−1][j−(n+1)]
由于每个体积不同,所以最多选出
n
\sqrt{n}
n 个
复杂度
Θ
(
n
n
)
\Theta(n\sqrt{n})
Θ(nn)
#include <bits/stdc++.h>
using namespace std;
namespace IO {
const int maxn((1 << 21) + 1);
char ibuf[maxn], *iS, *iT, c;
int f;
char Getc() {
return (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, maxn, stdin), (iS == iT ? EOF : *iS++)) : *iS++);
}
template <class Int> void In(Int &x) {
for (f = 1, c = Getc(); c < '0' || c > '9'; c = Getc()) f = c == '-' ? -1 : 1;
for (x = 0; c <= '9' && c >= '0'; c = Getc()) x = (x << 3) + (x << 1) + (c ^ 48);
x *= f;
}
}
using IO :: In;
const int mod(998244353);
const int maxn(2e5 + 5);
int fac[maxn], ifac[maxn], inv[maxn], n, m, f[500][maxn];
inline void Inc(int &x, int y) {
x += y;
if (x >= mod) x -= mod;
}
inline int C(int x, int y) {
if (y > x) return 0;
return 1LL * fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
int main() {
fac[0] = fac[1] = ifac[0] = ifac[1] = inv[1] = 1;
for (int i = 2; i <= 200000; ++i) {
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
fac[i] = 1LL * fac[i - 1] * i % mod;
ifac[i] = 1LL * ifac[i - 1] * inv[i] % mod;
}
In(n), In(m);
int sz = 500, ans = 0;
f[0][0] = 1;
for (int i = 1; i < sz; ++i)
for (int j = 0; j <= m; ++j) {
if (j >= i) f[i][j] = (f[i][j - i] - f[i - 1][j - i] + mod) % mod;
if (j >= n + 1) Inc(f[i][j], f[i - 1][j - n - 1]);
}
for (int i = 0; i <= m; ++i) {
int ret = 0;
for (int j = 0; j < sz; ++j) Inc(ret, f[j][i]);
Inc(ans, 1LL * ret * C(n + m - i - 1, n - 1) % mod);
}
printf("%d\n", ans);
return 0;
}