CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)
2014-08-13 13:43
495 查看
Codeforces Round #258 (Div. 2)
Devu and Flowers
题意:有N种花,每种最多f[i]枝,从中选s枝花,问有多少种选法。
题解:隔板法+容斥原理+Lucas定理算大组合数+求逆元
如此难的题,我不懂!我是看 http://hzwer.com/3810.html 学会的。
首先看没有f[i]枝数限制的话,可以用隔板法,N种花选s枝,相当于s个相同的球放到N个箱子有多少种放法。隔板法要求每个箱子至少放1个球,所以我们先增加N个假球来搞隔板法(相当于隔完板把每个盒子去掉一个球,就能算到有空的的情况了),N+s个球有N+s-1个空隙,分N个箱子需要N-1个隔板,种类数有C(N+s-1 , N-1)种。
然后观察有f[i]限制的情况。我们可以假装取超了,假装已经在第i个盒子取了f[i]+1个球,总球数减去(f[i]+1),可以算出第i个盒子取超了的种类数。
然后可能有0个盒子取超、1个盒子盒子取超、2个盒子取超……等等好多情况,这些情况还有互相重复的,这就要用到容斥原理。
ans=0个超的情况数 - 各种1个超的情况数 +各种2个超的情况数 - 各种3个超的情况数……
知道要算什么了,接下来看怎么算。
N<=20,s<=10^14,各种盒子取超的情况可以2^20枚举。算C(N+s-1 - ... , N-1)就比较难,不可能直接算。
用到Lacus定理:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p),左边继续递归Lacus,右边用逆元来算。
怎么用逆元:C(n,m)不是先算出分子和分母,然后分子除以分母嘛,我们可以当做用分子乘以分母的逆元。分母的逆元可以用超碉的一个定理:
费马小定理a^(p-1)=1(mod p),a为质数
a^(p-2)=a^(-1)(mod p),那么a^(p-2)就是a在modp意义下的逆元。
我们就用快速幂求出分母^(p-2),就是逆元了。
用这么多知识才能解E题,我都怕,是时候变碉了。
代码:
View Code
Devu and Flowers
E. Devu and Flowers time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Devu wants to decorate his garden with flowers. He has purchased n boxes, where the i-th box contains fi flowers. All flowers in a single box are of the same color (hence they are indistinguishable). Also, no two boxes have flowers of the same color. Now Devu wants to select exactly s flowers from the boxes to decorate his garden. Devu would like to know, in how many different ways can he select the flowers from each box? Since this number may be very large, he asks you to find the number modulo (109 + 7). Devu considers two ways different if there is at least one box from which different number of flowers are selected in these two ways. Input The first line of input contains two space-separated integers n and s (1 ≤ n ≤ 20, 0 ≤ s ≤ 1014). The second line contains n space-separated integers f1, f2, ... fn (0 ≤ fi ≤ 1012). Output Output a single integer — the number of ways in which Devu can select the flowers modulo (109 + 7). Sample test(s) Input 2 3 1 3 Output 2 Input 2 4 2 2 Output 1 Input 3 5 1 3 2 Output 3 Note Sample 1. There are two ways of selecting 3 flowers: {1, 2} and {0, 3}. Sample 2. There is only one way of selecting 4 flowers: {2, 2}. Sample 3. There are three ways of selecting 5 flowers: {1, 2, 2}, {0, 3, 2}, and {1, 3, 1}. |
题解:隔板法+容斥原理+Lucas定理算大组合数+求逆元
如此难的题,我不懂!我是看 http://hzwer.com/3810.html 学会的。
首先看没有f[i]枝数限制的话,可以用隔板法,N种花选s枝,相当于s个相同的球放到N个箱子有多少种放法。隔板法要求每个箱子至少放1个球,所以我们先增加N个假球来搞隔板法(相当于隔完板把每个盒子去掉一个球,就能算到有空的的情况了),N+s个球有N+s-1个空隙,分N个箱子需要N-1个隔板,种类数有C(N+s-1 , N-1)种。
然后观察有f[i]限制的情况。我们可以假装取超了,假装已经在第i个盒子取了f[i]+1个球,总球数减去(f[i]+1),可以算出第i个盒子取超了的种类数。
然后可能有0个盒子取超、1个盒子盒子取超、2个盒子取超……等等好多情况,这些情况还有互相重复的,这就要用到容斥原理。
ans=0个超的情况数 - 各种1个超的情况数 +各种2个超的情况数 - 各种3个超的情况数……
知道要算什么了,接下来看怎么算。
N<=20,s<=10^14,各种盒子取超的情况可以2^20枚举。算C(N+s-1 - ... , N-1)就比较难,不可能直接算。
用到Lacus定理:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p),左边继续递归Lacus,右边用逆元来算。
怎么用逆元:C(n,m)不是先算出分子和分母,然后分子除以分母嘛,我们可以当做用分子乘以分母的逆元。分母的逆元可以用超碉的一个定理:
费马小定理a^(p-1)=1(mod p),a为质数
a^(p-2)=a^(-1)(mod p),那么a^(p-2)就是a在modp意义下的逆元。
我们就用快速幂求出分母^(p-2),就是逆元了。
用这么多知识才能解E题,我都怕,是时候变碉了。
代码:
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<set> #include<stack> #include<queue> using namespace std; #define ll long long #define usint unsigned int #define mz(array) memset(array, 0, sizeof(array)) #define minf(array) memset(array, 0x3f, sizeof(array)) #define REP(i,n) for(i=0;i<(n);i++) #define FOR(i,x,n) for(i=(x);i<=(n);i++) #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define WN(x) printf("%d\n",x); #define RE freopen("D.in","r",stdin) #define WE freopen("1biao.out","w",stdout) const ll maxs=1e14; const ll MOD=1e9+7; ll a[22]; ll n,s,ans; ll PowerMod(ll a, ll b) { ll tmp = a, ret = 1; while (b) { if (b & 1) ret = ret * tmp % MOD; tmp = tmp * tmp % MOD; b >>= 1; } return ret; } ll calC(ll n,ll m){ m=n-m>m?m:n-m; ll up=1,down=1; int i; for(i=1;i<=m;i++){ down*=i; down%=MOD; up*=(n-i+1); up%=MOD; } return (up*PowerMod(down,MOD-2))%MOD; } ll Lucas(ll n, ll m) { if(m==0)return 1; return (Lucas(n/MOD, m/MOD)*calC(n%MOD, m%MOD))%MOD; } void attack(ll now,ll sum,ll flag){ if(sum<n)return; if(now==n){ //printf("%I64d C(%I64d,%I64d)=",flag,sum-1 , n-1); //printf("%I64d\n",Lucas(sum-1,n-1)); ans+=flag*Lucas(sum-1 , n-1); ans%=MOD; return; } attack(now+1,sum,flag); attack(now+1,sum-a[now]-1,-flag); } int main() { int i; scanf("%I64d%I64d",&n,&s); REP(i,n) scanf("%I64d",&a[i]); ans=0; attack(0,n+s,1); printf("%I64d\n",((ans%MOD)+MOD)%MOD); return 0; }
View Code
相关文章推荐
- 【HDU 3037】大数组合取模之Lucas定理+扩展欧几里得求逆元与不定方程一类问题
- hdu 3037 Saving Beans 【大组合数取模-Lucas定理+逆元取模】
- Codeforces 451E Devu and Flowers 容斥原理暴力+Lucas定理
- hdu 3929 Big Coefficients(Lucas定理+容斥原理)
- codeforces 451E Devu and Flowers(容斥原理,Lucas,dfs,隔板法)
- HDU 3037 Saving Beans (组合+Lucas定理+逆元+快速幂)
- BZOJ 1951 [Sdoi2010]古代猪文 欧拉定理+(扩展)lucas定理+逆元+快速幂
- Lucas定理 & 逆元学习小结
- [HDU 3037] Saving Beans (隔板法+lucas定理)
- hdoj 3037 lucas定理+逆元
- 【Lifht-oj】-1067-Combinations(Lucas定理&逆元)
- bzoj 1272: [BeiJingWc2008]Gate Of Babylon (容斥原理+Lucas定理)
- hdu3037 隔板法+Lucas定理求大组合取模
- 基于lucas定理线性求所有逆元的方法
- [Lucas定理 数位DP 容斥原理] 2015 计蒜之道 复赛 360的产品试用体验
- 【Lucas定理 && C(n, m)%p && 逆元】FZU - 2020 组合
- HDU 5794 A Simple Chess (容斥原理+Lucas定理+dp)
- 【BZOJ 2882】combination 推逆元+Lucas定理
- HDU - 5698 - 瞬间移动 - (除法求逆元,Lucas定理,组合数求路径)
- 组合数【Lucas定理,逆元】