2016 ACM/ICPC Reginal Shengyang hdu 5894 hannnnah_j’s Biological Test (数学推导 Lucas)

37 篇文章 0 订阅

题意:一个大小为 nn 的环,选 mm 个位置涂黑,要求相邻两个黑点之间至少间隔 kk 个白点,问方案数。

题解:

考虑每两个人之间隔了几把椅子。可以发现,一共有M个数,和为N-M,且每个数都>=K.将每个数都减去K-1,即得到:M个正数之和为N-K*M,方案数为C(N-K*M-1,M-1).需要乘以圆排列的N,同时每个方案被算了M次,再除以M。

答案为:C(N-K*M-1,M-1)*N/M。需要用预处理阶乘的方法计算组合数。注意特判M=1的情况。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <queue>
#include <map>
#include <bitset>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-3
#define maxn 1000100
#define MOD 1000000007

int n,m,k;
long long fac[1000010];


long long PowMod(long long a,long long b,long long mod)
{
    long long ret = 1;
    while(b)
    {
        if(b & 1)
            ret = (ret * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ret;
}
long long Get_Fact(long long p)
{
    fac[0] = 1;
    for(long long i = 1; i <= maxn; i++)
        fac[i] = (fac[i-1] * i) % p;
}
long long Lucas(long long n,long long m,long long p)
{
    long long ret = 1;
    while(n && m)
    {
        long long a = n % p;
        long long b = m % p;
        if(a < b)
            return 0;
        ret = (ret * fac[a] * PowMod(fac[b]*fac[a-b]%p,p-2,p)) % p;
        n /= p;
        m /= p;
    }
    return ret;
}
long long inv(long long a,long long m)
{
    if(a==1)
        return 1;
    return inv(m%a,m) * (m-m/a)%m;
}

int main()
{
    int t;
    scanf("%d",&t);
    Get_Fact(MOD);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        if(m == 1)
        {
            printf("%d\n",n);
            continue;
        }
        if(n-m*k-1 < m-1)
            printf("0\n");
        else
            printf("%lld\n",((Lucas(n-m*k-1,m-1,MOD)*n%MOD)*inv(m,MOD))%MOD);
    }
    return 0;
}


\geq >=k,相当于在一排(不是环) n-k的椅子中放m个人。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值