codeforces 451 E. Devu and Flowers

本文详细解析了一种经典的容斥模型问题,即从多种不同数量的花中选取特定数量的花的所有可能组合。通过转化为整数变量求和问题,利用数学组合公式与编程技巧,提供了一个高效求解方案。

有$n$种花,第$i$种有$f_i$朵,求从中选出$s$朵花的方案数

$1 \le n \le 20$

$0 \le s \le 10^{14}$

$0 \le f_i \le 10^{12}$

这不就是某经典容斥模型吗……

有$n$个整数变量,第$i$个变量的取值范围是$[0,f_i]$,求$\sum_{i=1}^{n}x_i=s$的方案数

枚举哪些变量超过限制,然后让它们强制变为$f_i+1+y_i$,这样就是一个没有限制的求方案数了,答案为${s+n-1 \choose n-1}$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod = 1e9 + 7;
 5 int n;
 6 ll sum, f[21], ans, inv[21];
 7 
 8 ll pw(ll a, ll b) {
 9     ll r = 1;
10     for( ; b ; b >>= 1, a = a * a % mod) if(b & 1) r = r * a % mod;
11     return r;
12 }
13 
14 int main() {
15     cin >> n >> sum;
16     for(int i = 0 ; i < n ; ++ i) cin >> f[i], inv[i] = pw(i, mod - 2);
17     for(int s = 0 ; s < (1 << n) ; ++ s) {
18         int cnt = 0;
19         ll tot = 0;
20         for(int i = 0 ; i < n ; ++ i) {
21             if((s >> i) & 1) {
22                 ++ cnt;
23                 tot += f[i] + 1;
24                 if(tot > sum) { tot = -1; break; }
25             }
26         }
27         if(tot == -1) continue;
28         tot = sum - tot;
29         // C(tot + n - 1, n - 1) = (tot + n - 1)! / (n - 1)! / (tot)!
30         ll tmp = 1;
31         for(ll i = tot + 1 ; i <= tot + n - 1 ; ++ i) (tmp *= i % mod) %= mod;
32         for(ll i = 1 ; i <= n - 1 ; ++ i) (tmp *= inv[i] % mod) %= mod;
33         if(tmp < 0) cout << "tmp = " << tmp << endl;
34         ans = (ans + (cnt & 1 ? -1 : 1) * tmp) % mod;
35     }
36     ans = (ans % mod + mod) % mod;
37     cout << ans << endl;
38 }
codeforces 451 E. Devu and Flowers

转载于:https://www.cnblogs.com/KingSann/articles/9558166.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值