2015 HIAST Collegiate Programming Contest D

Time to go back

题意:一个礼物店里有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;
}
原文地址:https://www.cnblogs.com/max88888888/p/7161829.html