hdu5894 hannnnah_j’s Biological Test(组合数取模)

题意:

n个桌子围成圈m个人,间隔至少k个桌子,问方案数

思路:

这可以推出来一个公式C(n-m*k-1,m-1),然后第一个人有n中选择,每个人是相等的

所以就*n/m就好了,除改成乘逆元就好了

/* ***********************************************
Author        :devil
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
#define inf 0x3f3f3f3f
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ou(a) printf("%d\n",a)
#define pb push_back
#define mkp make_pair
template<class T>inline void rd(T &x){char c=getchar();x=0;while(!isdigit(c))c=getchar();while(isdigit(c)){x=x*10+c-'0';c=getchar();}}
#define IN freopen("in.txt","r",stdin);
#define OUT freopen("out.txt","w",stdout);
using namespace std;
const int mod=1e9+7;
const int N=1e6+10;
int f[N];
int inv(int x)
{
    int ret=1,y=mod-2;
    while(y)
    {
        if(y&1)ret=1ll*ret*x%mod;
        y>>=1;
        x=1ll*x*x%mod;
    }
    return ret;
}
int C(int n,int m)
{
    if(n<m) return 0;
    int ret=1ll*f[n]*inv(f[m])%mod;
    ret=1ll*ret*inv(f[n-m])%mod;
    return ret;
}
int lucas(int n,int m)
{
    if(!m) return 1;
    return 1ll*C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
void init()
{
    f[0]=1;
    for(int i=1;i<=N-10;i++) f[i]=1ll*i*f[i-1]%mod;
}
int main()
{
    init();
    int t;
    rd(t);
    LL n,m,k;
    while(t--)
    {
        rd(n),rd(m),rd(k);
        if(m>1&&n<m*(k+1))
        {
            printf("0\n");
            continue;
        }
        printf("%lld\n",((lucas(n-m*k-1,m-1)*n)%mod*inv(m))%mod);
    }
    return 0;
}

 

posted on 2016-09-21 17:07  恶devil魔  阅读(236)  评论(0编辑  收藏  举报

导航