Devu和鲜花
Devu和鲜花
Devu 有 个盒子,第 个盒子中有 枝花。
同一个盒子内的花颜色相同,不同盒子内的花颜色不同。
Devu 要从这些盒子中选出 枝花组成一束,求共有多少种方案。
若两束花每种颜色的花的数量都相同,则认为这两束花是相同的方案。
结果需对 取模之后方可输出。
输入格式
第一行包含两个整数 和 。
第二行包含 个空格隔开的整数,表示 。
输出格式
输出一个整数,表示方案数量对 取模后的结果。
数据范围
,
,
输入样例:
3 5 1 3 2
输出样例:
3
解题思路
这题是用容斥原理来做的。
先考虑每个盒子中花的数量为无限个,假设表示在第个盒子中选择花的数量,由于要从个盒子中选择枝花,因此有,其中。最终选法的个数就是这个方程的非负整数解的个数。这个可以用隔板法来求,由于在隔板法中要求变量的值为正整数,因此还需要对这个方程做一个映射。设,因此有,等式就变成了,因此正整数解的方案数就是。
在原问题中每个盒子选择花的数量是有限制的,即要求,而上面的做法是没有限制的情况(即总方案数),为了通过没有限制的情况得到有限制的情况,这里就可以用容斥原理了。由于有个条件要同时满足,我们可以求补集,即求至少有一个条件不满足的方案数量,然后用总的方案数量减去至少有一个条件不满足的方案数量,得到的结果就是同时满足个条件的数量。
如果第个条件不满足,那么就是。设集合表示不满足第个条件的方案,因此同时满足个条件的方案数就是
先分析一下如何求。第个盒子至少要拿枝花,那么我们先从第个盒子取出枝花,此时问题就变成了从个盒子中选择枝花。为什么还要从第个盒子取花?这是因为第个盒子至少要取枝花,因此第个盒子还可以选,先取出枝花,后面不管从第个盒子取多少花最终都至少从第个盒子取出超过枝花。因此有。
因此,那么呢?同理先从第个盒子取出枝花,再从第个盒子取出枝花,问题就变成了从个盒子中选择枝花,方案数就是 。以此类推来求的方案数。
因此可以通过二进制枚举来实现求容斥原理的过程。
其中由于最大只有,因此公式中的组合数直接按照定义来算就可以了。除法用乘法逆元,由于取模的数是质数,最大取到,因此必然与互质,因此可以用费马小定理来求逆元。注意到公式中的组合数都是取出个数,即分母都是,因此可以先预处理出的逆元,这样每次求组合数就不需要重复计算了。
AC代码如下,时间复杂度为:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 30, mod = 1e9 + 7; 7 8 LL p[N]; 9 LL down = 1; // (n-1)!的逆元 10 11 int qmi(int a, int k) { 12 int ret = 1; 13 while (k) { 14 if (k & 1) ret = 1ll * ret * a % mod; 15 a = 1ll * a * a % mod; 16 k >>= 1; 17 } 18 return ret; 19 } 20 21 int C(LL a, LL b) { // 从a个里面选b个 22 if (a < b) return 0; 23 int up = 1; // 分子 24 for (LL i = a; i > a - b; i--) { 25 up = i % mod * up % mod; 26 } 27 return up * down % mod; // 分子乘以分母的逆元 28 } 29 30 int main() { 31 LL n, m; 32 scanf("%lld %lld", &n, &m); 33 for (int i = 0; i < n; i++) { 34 scanf("%lld", p + i); 35 } 36 for (int i = 1; i < n; i++) { 37 down = down * i % mod; 38 } 39 down = qmi(down, mod - 2); // 求分母的逆元 40 int ret = C(m + n - 1, n - 1); 41 for (int i = 1; i < 1 << n; i++) { 42 LL a = m + n - 1, b = n - 1, cnt = 0; 43 for (int j = 0; j < n; j++) { 44 if (i >> j & 1) a -= p[j] + 1, cnt ^= 1; 45 } 46 if (cnt) ret = (ret - C(a, b)) % mod; 47 else ret = (ret + C(a, b)) % mod; 48 } 49 printf("%d", (ret + mod) % mod); 50 51 return 0; 52 }
参考资料
AcWing 214. Devu和鲜花(算法提高课):https://www.acwing.com/video/739/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17144554.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-02-22 数星星