Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P5824 十二重计数法

P5824 十二重计数法

球不同,盒不同

$\text I$

每个球都是独立的,各有 $m$ 个选择。答案为 $m ^ n$ 。

$\text {II}$

每选择一个盒子后,可以选择的方案少一个,即 $m ^ {\underline n}$ 。

$\text {III}$

记 $f (x)$ 表示钦定 $x$ 个盒子为空的方案数,$g(x)$ 表示恰有 $x$ 个盒子为空的答案。那么有 $f(x) = (m - x) ^ n = \sum _ {i = x} \binom i x g(i)$ 。由二项式反演,$g(x) = \sum _ {i = x} (-1) ^ {i - x}\binom i x f(i) $ ,那么 $g(0) = \sum _ {i = 0} (-1) ^ i \binom i x (m - i) ^ n$ 。

球不同,盒相同

$\text {IV}$

枚举有多少个集合为空,集合非空时即为第二类斯特林数,答案为 $\sum _ {i = 1} ^ m {n \brace i}$ 。

$\text V$

对于 $n > m$ ,答案为 $0$ 。对于 $n < m$ ,所有盒子相同,方案为 $1$ 。

$\text {VI}$

即第二类斯特林数 ${n \brace m}$ 。

球相同,盒不同

$\text {VII}$

插板法,答案为 $binom {n + m - 1} {m - 1}$ 。

$\text {VIII}$

$m$ 个盒子里面选择 $n$ 个不为空,答案为 $\binom m n $ 。

$\text {IX}$

插板法,答案为 $\binom {n - 1} {m - 1}$ 。

球相同,盒相同

$\text X$

直接统计是困难的。考虑按照这样的办法统计答案:每一次操作选择前 $i \in [1, m]$ 个盒子使球的个数 +1 。这样只用 $m$ 种操作即可刻画出答案。那么问题变化为使用体积为 $[1, m]$ 的物品装满体积为 $n$ 的背包的方案数,那么和 付公主的背包 是一样的了。

$\text {XI}$

对于 $n > m$ ,答案为 $0$ 。对于 $n < m$ ,所有盒子相同,方案为 $1$ 。

$\text {XII}$

将每个盒子放一个球后,和 $\text X$ 是一样的。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <cstdio>
#include <algorithm>
using namespace std;
template <class Type>
void read (Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0';
flag && (x = ~x + 1);
}
template <class Type, class ...rest>
void read (Type &x, rest &...y) { read(x), read(y...); }
template <class Type>
void write (Type x)
{
x < 0 && (putchar('-'), x = ~x + 1);
x > 9 && (write(x / 10), 0);
putchar('0' + x % 10);
}
typedef long long LL;
const int N = 1e6 + 10, mod = 998244353;
int n, m, rev[N], inv[N], fact[N], ifact[N], sn[N], pm[N];
int binpow (int b, int k = mod - 2)
{
int res = 1;
for (; k; k >>= 1, b = (LL)b * b % mod)
if (k & 1) res = (LL)res * b % mod;
return res;
}
void ntt (int *x, int bit, int op)
{
int tot = 1 << bit;
for (int i = 1; i < tot; ++i)
if ((rev[i] = rev[i >> 1] >> 1 | (i & 1) << bit - 1) > i)
swap(x[rev[i]], x[i]);
for (int mid = 1; mid < tot; mid <<= 1)
{
int w1 = binpow(3, (mod - 1) / (mid << 1));
if (!~op) w1 = binpow(w1);
for (int i = 0; i < tot; i += mid << 1)
for (int j = 0, k = 1; j < mid; ++j, k = (LL)k * w1 % mod)
{
int p = x[i | j], q = (LL)k * x[i | j | mid] % mod;
x[i | j] = (p + q) % mod, x[i | j | mid] = (p - q) % mod;
}
}
if (~op) return;
int itot = binpow(tot);
for (int i = 0; i < tot; ++i)
x[i] = (LL)x[i] * itot % mod;
}
void PolyMul (int n, int *f, int m, int *g, int nm, int *res)
{
int bit = 0;
while (1 << bit < n + m - 1) ++bit;
int tot = 1 << bit;
for (int i = n; i < tot; ++i) f[i] = 0;
for (int i = m; i < tot; ++i) g[i] = 0;
ntt(f, bit, 1), ntt(g, bit, 1);
for (int i = 0; i < tot; ++i)
res[i] = (LL)f[i] * g[i] % mod;
ntt(res, bit, -1);
for (int i = nm; i < tot; ++i) res[i] = 0;
}
void PolyInv(int n, int *x, int *g)
{
if (n == 1) return void(g[0] = binpow(x[0]));
int m = n + 1 >> 1;
int bit = 0;
while (1 << bit < n + m + m - 2) ++bit;
int tot = 1 << bit;
PolyInv(m, x, g);
for (int i = m; i < tot; ++i) g[i] = 0;
static int A[N];
for (int i = 0; i < n; ++i) A[i] = x[i];
for (int i = n; i < tot; ++i) A[i] = 0;
ntt(g, bit, 1), ntt(A, bit, 1);
for (int i = 0; i < tot; ++i)
g[i] = (2 - (LL)g[i] * A[i]) % mod * g[i] % mod;
ntt(g, bit, -1);
for (int i = n; i < tot; ++i) g[i] = 0;
}
void PolyDerivate(int n, int *x, int *g)
{
for (int i = 1; i < n; ++i)
g[i - 1] = (LL)x[i] * i % mod;
g[n - 1] = 0;
}
void PolyIntegrate(int n, int *x, int *g)
{
for (int i = 1; i < n; ++i)
g[i] = (LL)x[i - 1] * binpow(i) % mod;
g[0] = 0;
}
void PolyLn(int n, int *x, int *g)
{
static int A[N], B[N];
PolyDerivate(n, x, A);
PolyInv(n, x, B);
PolyMul(n, A, n, B, n, A);
PolyIntegrate(n, A, g);
}
void PolyExp(int n, int *x, int *g)
{
if (n == 1) return void(g[0] = 1);
int m = n + 1 >> 1;
PolyExp(m, x, g);
for (int i = m; i < n; ++i) g[i] = 0;
static int A[N];
PolyLn(n, g, A);
for (int i = 0; i < n; ++i)
A[i] = (x[i] - A[i]) % mod;
++A[0];
PolyMul(n, A, m, g, n, g);
}
void init ()
{
inv[1] = 1;
for (int i = 2; i < N; ++i)
inv[i] = -(LL)inv[mod % i] * (mod / i) % mod;
fact[0] = ifact[0] = 1;
for (int i = 1; i < N; ++i)
{
fact[i] = (LL)fact[i - 1] * i % mod;
ifact[i] = (LL)ifact[i - 1] * inv[i] % mod;
}
}
int C (int a, int b) { return a < b ? 0 : (LL)fact[a] * ifact[b] % mod * ifact[a - b] % mod; }
int main ()
{
init();
read(n, m);
{
static int A[N], B[N];
for (int i = 0; i <= n; i++)
A[i] = (LL)binpow(i, n) * ifact[i] % mod;
for (int i = 0; i <= n; i++)
B[i] = ifact[i] * (i & 1 ? -1 : 1);
PolyMul(n + 1, A, n + 1, B, n + 1, sn);
}
{
static int A[N];
for (int i = 1; i <= m; ++i)
for (int j = 1; i * j <= n; ++j)
(A[i * j] += inv[j]) %= mod;
PolyExp(n + 1, A, pm);
}
write(binpow(m, n)), puts("");
write(n <= m ? ((LL)fact[m] * ifact[m - n] % mod + mod) % mod : 0), puts("");
{
int res = 0;
for (int i = 0; i <= m; ++i)
(res += (i & 1 ? -1ll : 1ll) * C(m, i) * binpow(m - i, n) % mod) %= mod;
write((res + mod) % mod), puts("");
}
{
int res = 0;
for (int i = 1; i <= min(n, m); ++i)
(res += sn[i]) %= mod;
write((res + mod) % mod), puts("");
}
write(n <= m), puts("");
write((sn[m] + mod) % mod), puts("");
write((C(n + m - 1, m - 1) + mod) % mod), puts("");
write((C(m, n) + mod) % mod), puts("");
write((C(n - 1, m - 1) + mod) % mod), puts("");
write((pm[n] + mod) % mod), puts("");
write(n <= m), puts("");
write(n <= m ? 0 : (pm[n - m] + mod) % mod), puts("");
return 0;
}