[题解]CF451E Devu and Flowers
思路
Part 1 简单版#
我们先想一想,如果每一种花有无限个,有多少种选法。
我们先假设第 种花选 支,那么,我们可以得出以下式子:
然后,我们根据隔板法,得出答案:。
Part 2 本题#
对于这题,拥有了一个 的条件,比较棘手,于是,我们可以通过容斥原理的方法来做。
这里,我们可以用正难则反的思想,求出至少有一个 的数量。
我们定义 表示不满足 的数量。
那么,我们的答案就是:。
通过容斥原理,得:。
那么,我们的 怎么求呢?
我们可以先假设 为 ,因此,我们的 就为 。
例如:。
然后,我们也是通过状态压缩的方式解决。
Code
#include <bits/stdc++.h>
#define int long long
#define re register
using namespace std;
const int N = 25,mod = 1e9 + 7;
int n,m,inv,ans,sum = 1;
int arr[N];
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
inline int exgcd(int a,int b,int &x,int &y){//拓展欧几里得算法求逆元
if (!b){
x = 1;
y = 0;
return a;
}
int d = exgcd(b,a % b,y,x);
y = y - a / b * x;
return d;
}
inline int C(int a,int b){//组合数
if (a < b) return 0;
int x = 1;
for (re int i = a;i > a - b;i--) x = i % mod * x % mod;
return x % mod * inv % mod;
}
signed main(){
n = read();
m = read();
for (re int i = 1;i <= n;i++) arr[i] = read();
for (re int i = 1;i <= n - 1;i++) sum = sum * i % mod;
int x,y;
exgcd(sum,mod,x,y);//求逆元
inv = (x + mod) % mod;
for (re int i = 0;i <= (1 << n) - 1;i++){//状态压缩枚举
int cnt = 0;
int a = n + m - 1,b = n - 1;
for (int j = 1;j <= n;j++){
if ((i >> j - 1) & 1){
cnt++;
a = a - (arr[j] + 1);
}
}
if (cnt & 1) ans = (ans - C(a,b)) % mod;
else ans = (ans + C(a,b)) % mod;
}
printf("%lld",(ans + mod) % mod);
return 0;
}
作者:WaterSun
出处:https://www.cnblogs.com/WaterSun/p/18263301
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】