大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。
题目链接:Codeforces 451E Devu and Flowers
题目大意:有n个花坛。要选s支花,每一个花坛有f[i]支花。同一个花坛的花颜色同样,不同花坛的花颜色不同,问说能够有多少种组合。
解题思路:2n的状态,枚举说那些花坛的花取超过了,剩下的用C(n−1sum+n−1)隔板法计算个数。注意奇数的位置要用减的。偶数的位置用加的。容斥原理。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
//ll n, m, p;
ll qPow (ll a, ll k, ll p) {
ll ans = 1;
while (k) {
if (k&1)
ans = (ans * a) % p;
a = (a * a) % p;
k /= 2;
}
return ans;
}
ll C (ll a, ll b, ll p) {
if (a < b)
return 0;
if (b > a - b)
b = a - b;
ll up = 1, down = 1;
for (ll i = 0; i < b; i++) {
up = up * (a-i) % p;
down = down * (i+1) % p;
}
return up * qPow(down, p-2, p) % p; // 逆元
}
ll lucas (ll a, ll b, ll p) {
if (b == 0)
return 1;
return C(a%p, b%p, p) * lucas(a/p, b/p, p) % p;
}
const int maxn = 25;
const ll mod = 1e9+7;
int n;
ll s, f[maxn];
ll solve () {
ll ans = 0;
for (int i = 0; i < (1<<n); i++) {
ll sign = 1, sum = s;
for (int j = 0; j < n; j++) {
if (i&(1<<j)) {
sum -= (f[j]+1);
sign *= -1;
}
}
if (sum < 0)
continue;
ans += sign * lucas(sum + n - 1, n - 1, mod);
ans %= mod;
}
return (ans + mod) % mod;
}
int main () {
scanf("%d%lld", &n, &s);
for (int i = 0; i < n; i++)
scanf("%lld", &f[i]);
printf("%lld\n", solve());
return 0;
}
版权声明:本文博主原创文章,博客,未经同意不得转载。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116975.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...