214. Devu和鲜花

题目链接

214. Devu和鲜花

Devu 有 N 个盒子,第 i 个盒子中有 A_i 枝花。

同一个盒子内的花颜色相同,不同盒子内的花颜色不同。

Devu 要从这些盒子中选出 M 枝花组成一束,求共有多少种方案。

若两束花每种颜色的花的数量都相同,则认为这两束花是相同的方案。

结果需对 109+7 取模之后方可输出。

输入格式

第一行包含两个整数 NM

第二行包含 N 个空格隔开的整数,表示 A1,A2,,AN

输出格式

输出一个整数,表示方案数量对 109+7 取模后的结果。

数据范围

1N20,
0M1014,
0Ai1012

输入样例:

3 5 1 3 2

输出样例:

3

解题思路

容斥原理

考虑鲜花个数不限的情况,即满足 x1+x2++xn=m,其中 x1,x2,,xn0,设 yi=xi+1,则 y1+y2++yn=m+n,其中 y1,y2,,yn1,即转化为在 n+m1 中插 n1 个板子的隔板问题,方案数为 Cn+m1n1,然后要求 s1+s2++sn=m,其中 si 表示满足 xiai 的条件,由容斥定理有 s1s2sn=Cn+m1n1(s1s2sn),其中 (s1s2sn) 表示至少有一个 si 不满足条件,当只有 s1 不满足条件时,即 x1 至少选了 a1+1 个数,选走 a1+1 个数后,还剩 m(a1+1) 个数,此时又可通过隔板问题得方案数 Cn+m1(a1+1)n1,其他单个不满足条件同理,同时对于多个单个条件同时满足时也需要考虑容斥,最后答案为 Cn+m1n1i=0i=n1Cn+m1(ai+1)n1+i=0,ijj=n1Cn+m1(ai+1)(aj+1)n1

  • 时间复杂度:(n×2n)

代码

// Problem: Devu和鲜花 // Contest: AcWing // URL: https://www.acwing.com/problem/content/216/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> // #define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=20,mod=1e9+7; int n,res,t=1; LL a[N],m; int ksm(int a,int b,int p) { int res=1%p; while(b) { if(b&1)res=1ll*res*a%p; a=1ll*a*a%p; b>>=1; } return res; } int C(LL a) { if(a<n-1)return 0; int res=1; for(LL i=a;i>=a-n+2;i--)res=i%mod*res%mod; return 1ll*res*t%mod; } int main() { cin>>n>>m; for(int i=1;i<n;i++)t=1ll*t*i%mod; t=ksm(t,mod-2,mod); for(int i=0;i<n;i++)cin>>a[i]; for(int i=0;i<(1<<n);i++) { LL b=n+m-1,sign=1; for(int j=0;j<n;j++) if(i>>j&1)b-=a[j]+1,sign*=-1; res=(res+C(b)*sign)%mod; } cout<<(res+mod)%mod; return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16418991.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示