题目链接: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;}
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow
本文详细解析了Codeforces451E题目“Devu and Flowers”的解题思路,利用状态压缩和容斥原理,通过隔板法计算选取特定数量花朵的不同组合方式。
484

被折叠的 条评论
为什么被折叠?



