CF gym10143 A

题目在这里>_<

题意

有m家巧克力店,要去其中的n家,从中买k个巧克力。每家店最多只能买一个巧克力。进某家店的概率为p,进了店就一定会买巧克力。问在第n家店(最后一家店)买第k块(最后一块)巧克力的概率是多少。答案对1000000007取模。

思路

可以很容易的得到答案是$C_{n}^kp^k(1-p)^{n-k}$ 。看到p是一个三位小数,因此给p乘1000便得到了整数。进每家店的概率便成了$\frac{p}{1000}$ 。所以就是直接求原式对1000000007取模。其中分母的部分都求逆元即可。这里因为模数是个质数,所以直接用费马小定理就可以求逆元了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <set>
//#define test
using namespace std;
const int Nmax=1e6+7;
typedef unsigned long long ll;
const ll mod = 1000000007LLu;
ll n,m,k,ans,p;
double p0;
ll qmod(ll base,ll t)
{
    ll ans=1LLu;
    base=base%mod;
    while(t)
    {
        if(t&1LLu)
            ans=(ans*base)%mod;
        base=(base*base)%mod;
        t>>=1;
    }
    while(ans<0)
        ans+=mod;
    return ans;
}
int main()
{
    #ifdef test
    #endif
    scanf("%llu%llu%llu%lf",&m,&n,&k,&p0);
    if(n>m)
        return 0*printf("0\n");
    if(k>n)
        return 0*printf("0\n");
    //p=(1LLu)*1000*p0;
    p=(1LLu)*floor(p0*1000.0+1e-10);
    //printf("p:%llu\n",p);
    ll inv=qmod(1000LLu,mod-2LLu);
    //printf("inv:%llu\n",inv);
    //printf("%llu\n",3741175000LLu%mod);
    ll a=(p*inv)%mod;
    ll b=((1000LLu-p)*inv)%mod;
    //printf("a:%llu\n",a);
    //printf("b:%llu\n",b);
    a=qmod(a,k);
    b=qmod(b,n-k);
    //printf("new a:%llu\n",a);
    //printf("new b:%llu\n",b);
    ans=(a*b)%mod;
    //printf("ans:%llu\n",ans);
    ll t=k-1;
    ll tmp=1LLu;
    ll ta=n-1,tb=k-1;
    while(t--)
    {
        tmp=tmp*ta%mod;
        tmp=tmp*qmod(tb,mod-2)%mod;
        ta--;
        tb--;
    }
    tmp=tmp%mod;
    while(tmp<=0)
        tmp+=mod;
    //printf("tmp:%llu\n",tmp);
    ans=ans*tmp%mod;
    while(ans<0)
        ans+=mod;
    printf("%llu\n",ans);
    return 0;
}