题意:一个礼物店里有m个礼物,你需要买n个礼物给你的朋友,其中有k个是很亲密的朋友,他们的礼物价格不能低于D,求一共有多少种买礼物的方法,并对1e9+7取模
思路:一共需要买m个礼物,那么可以求出一个x的范围为 mi<=x<=ma,mi=max(m-n+nd,k), mx=min(nd,m), x表示在价格不低于D的礼物的个数,所有情况相加并取模就是答案,由于要取模,所以用lucas写
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define ll long long #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a) memset(a,0,sizeof(a)) #define mp(x,y) make_pair(x,y) using namespace std; const long long INF = 1e18+1LL; const int inf = 1e9+1e8; const int N=1e5+100; ///2015 HIAST Collegiate Programming Contest const ll Mod=1e9+7; ll exp_mod(ll a, ll b, ll p) { ll res = 1; while(b != 0) { if(b&1) res = (res * a) % p; a = (a*a) % p; b >>= 1; } return res; } ll Comb(ll a, ll b, ll p) { if(a < b) return 0; if(a == b) return 1; if(b > a - b) b = a - b; ll ans = 1, ca = 1, cb = 1; for(ll i = 0; i < b; ++i) { ca = (ca * (a - i))%p; cb = (cb * (b - i))%p; } ans = (ca*exp_mod(cb, p - 2, p)) % p; return ans; } ll Lucas(int n, int m, int p) { ll ans = 1; while(n&&m&&ans) { ans = (ans*Comb(n%p, m%p, p)) % p; n /= p; m /= p; } return ans; } int n,m,k,d,nd,ns,t; int price[205]; int main(){ cin>>t; while(t--){ ll ans=0; nd=0; cin>>n>>m>>k>>d; for(int i=1; i<=n; ++i){ cin>>price[i]; if(price[i]>=d) nd++; } ns=n-nd;// cout<<nd<<" "; if(k>nd || n<m){ cout<<0<<endl; continue; } int mi=max(m-n+nd,k), mx=min(nd,m); for(int i=mi; i<=mx; ++i){ ans+=Lucas(nd,i,Mod)*Lucas(ns,m-i,Mod); ans%=Mod; } cout<<(ans+Mod)%Mod<<endl; } return 0; }