1 条题解
-
0
自动搬运
来自洛谷,原作者为

CYJian
今日はこっちの地方はどしゃぶりの晴天でした,昨日もずっと暇で一日満喫してました搬运于
2025-08-24 22:14:41,当前版本为作者最后更新于2020-01-13 11:56:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
个球, 个盒子
一、球不同,盒子不同,无其他限制
显然为
二、球不同,盒子不同,每个盒子至多装一个球
考虑相当于每个球找一个没有被选过的盒子放进去。不难发现,方案数为
三、球不同,盒子不同,每个盒子至少装一个球
考虑容斥:枚举多少个盒子空了,然后剩下的部分就是第一个部分了。然后就可以得到下面这个式子:
四、球不同,盒子相同,无其他限制
考虑第二类斯特林数: 表示 个不同的元素组成 个非空集合的方案数。
考虑枚举多少个盒子里头装了球,那么答案为:
蒯 第二类斯特林数 · 行 就行了
五、球不同,盒子相同,每个盒子至多装一个球
最思博的部分了不论放到哪个盒子里头都是一样的,所以答案就是六、球不同,盒子相同,每个盒子至少装一个球
根据第二类斯特林数的定义,显然答案为
七、球相同,盒子不相同,无其他限制
利用插板法,我们可以知道,答案为
八、球相同,盒子不相同,每个盒子至多装一个球
盒子不同,我们相当于要选出 个盒子装球,剩下 个盒子不装球。
所以答案就是
九、球相同,盒子不相同,每个盒子至少装一个球
同样利用插板法,我们先钦定每个盒子里头放一个球,剩下 个球按照第七个做就行了。
答案即为
十、球相同,盒子相同,无其他限制
设 表示“划分数”——即将 划分成 个自然数的可重集的方案数。那么我们要的答案就是
这个东西有一个非常经典的时空复杂度为 的 :
两者的意思分别为:将 个 自然数同时 、加入一个 到可重集中。
不难发现这样的确可以不重不漏地计数。
再考虑优化:我们构造一个多项式为:
$$F_i(x)=p_{0,i}+p_{1,i}x+p_{2,i}x^{2}+p_{3,i}x^{3} \dots $$那么根据上面的转移,我们有:
$$F_i(x) = F_{i-1}(x) \times (1+x^i+x^{2i}+x^{3i}\dots) $$那么也就不难得到:
这个东西和 付公主的背包 是一样的。具体做法就是求 ,加起来再 回去,最后求个逆就完了。
考虑这个东西如何快速求 :
$$G'(x) = (-ix^{i-1}) \times \sum_{j=0}^{\infty} x^{ij} $$然后在模 意义下做这个东西就完事了。
十一、球相同,盒子相同,每个盒子至多装一个球
和第五个是一样的东西,就是 。
十二、球相同,盒子相同,每个盒子至少装一个球
考虑就是将上面的“划分数”中的自然数变成正整数,我们强制现在每个盒子里头放一个球,就是同样的问题了。答案即为 。
完整代码 比较长,这里略去多项式板子以及基础数论部分的代码(因为用的是 vim,所以可能有很多折叠标记)
/******************************************************************************** Code by a weak man who named CYJian, and he hopes the code can get more scores. Algorithm: ********************************************************************************/ #include <bits/stdc++.h> using namespace std; typedef long long ll; //{{{ FAST IO const int __SIZE = 1 << 18; char ibuf[__SIZE], *iS, *iT; #define ge (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin), (iS == iT ? EOF : *iS++)) : *iS++) #define ri read_int() #define rl read_ll() #define FILE(s) freopen(s"in", "r", stdin), freopen(s"out", "w", stdout) template<typename T> inline void read(T &x) { char ch, t = 0; x = 0; while(!isdigit(ch = ge)) t |= ch == '-'; while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = ge; x = t ? -x : x; } inline int read_int() { int x; return read(x), x; } inline ll read_ll() { ll x; return read(x), x; } //}}} template<typename T> inline void chkmin(T&a, T b) { a = a < b ? a : b; } template<typename T> inline void chkmax(T&a, T b) { a = a > b ? a : b; } const int MAXN = 530010; const int mod = 998244353; inline int Mod(int x) { return x >= mod ? x - mod : x; } inline void Add(int &x, int y) { x += y, x -= x >= mod ? mod : 0; } int n, m; int fac[MAXN]; int inv[MAXN]; int ifac[MAXN]; int tN; int N, InvN; int p[MAXN]; int G[MAXN]; int S[MAXN]; int F[MAXN]; int A[MAXN]; int B[MAXN]; int tA[MAXN]; int tB[MAXN]; int tC[MAXN]; int tD[MAXN]; //{{{ Math And Prework inline int fsp(int x, int k = mod - 2) {}// 快速幂 inline int C(int n, int m) {} // 组合数 inline void Combine_init(int n) {} // 预处理阶乘以及逆元 inline void Prework() {} // 预处理原根 inline void NTT_init(int n) {} inline void NTT(int a[], int k) {} // 快速数论变换 inline void GetInv(int A[], int B[], int n) {} // 多项式求逆 inline void GetLn(int A[], int B[], int n) {} // 多项式求对数 inline void GetExp(int A[], int B[], int n) {} // 多项式 exp inline void init(int n, int m) { Prework(), Combine_init(n + m), NTT_init(max(n, m)); for(int i = 0; i <= n; i++) { A[i] = i & 1 ? mod - ifac[i] : ifac[i]; B[i] = 1LL * fsp(i, n) * ifac[i] % mod; } NTT(A, 1), NTT(B, 1); for(int i = 0; i < N; i++) A[i] = 1LL * A[i] * B[i] % mod; NTT(A, -1); for(int i = 0; i <= n; i++) S[i] = A[i]; // 第二类斯特林数 memset(A, 0, sizeof(A)); for(int i = 1; i <= m; i++) for(int j = i; j <= n; j += i) Add(A[j], mod - inv[j / i]); memset(B, 0, sizeof(B)), GetExp(A, B, n + 1); memset(A, 0, sizeof(A)), GetInv(B, A, n + 1); for(int i = 0; i <= n; i++) F[i] = A[i]; // p_{i, m} } //}}} //{{{ solve01 inline int solve01() { return fsp(m, n); } //}}} //{{{ solve02 inline int solve02() { int res = 1; for(int i = 0; i < n; i++) res = 1LL * res * (m - i) % mod; return res; } //}}} //{{{ solve03 inline int solve03() { int res = 0; for(int i = 0; i < m; i++) res = (res + 1LL * (i & 1 ? mod - C(m, i) : C(m, i)) * fsp(m - i, n)) % mod; return res; } //}}} //{{{ solve04 inline int solve04() { int res = 0; for(int i = 1; i <= m; i++) Add(res, S[i]); return res; } //}}} //{{{ solve05 inline int solve05() { return n <= m; } //}}} //{{{ solve06 inline int solve06() { return S[m]; } //}}} //{{{ solve07 inline int solve07() { return C(n + m - 1, m - 1); } //}}} //{{{ solve08 inline int solve08() { return C(m, n); } //}}} //{{{ solve09 inline int solve09() { return C(n - 1, m - 1); } //}}} //{{{ solve10 inline int solve10() { return F[n]; } //}}} //{{{ solve11 inline int solve11() { return n <= m; } //}}} //{{{ solve12 inline int solve12() { return n >= m ? F[n - m] : 0; } //}}} int main() { #ifdef LOCAL FILE(""); #endif n = ri, m = ri, init(n, m); cout << solve01() << endl; cout << solve02() << endl; cout << solve03() << endl; cout << solve04() << endl; cout << solve05() << endl; cout << solve06() << endl; cout << solve07() << endl; cout << solve08() << endl; cout << solve09() << endl; cout << solve10() << endl; cout << solve11() << endl; cout << solve12() << endl; return 0; }
- 1
信息
- ID
- 4759
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者