首页 > 代码库 > HDU 5894 hannnnah_j’s Biological Test (组合数学) -2016 ICPC沈阳赛区网络赛

HDU 5894 hannnnah_j’s Biological Test (组合数学) -2016 ICPC沈阳赛区网络赛

题目链接

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

题解:考虑从 0 开始的标号最小的涂黑的位置,有两种情况:

如果该位置 \geq kk,相当于在一排(不是环) n - knk 个椅子里面放 mm 个人;
如果该位置 < k<k, 相当于在一排 n - 2k - 1n2k1 个椅子里面放 (m - 1)(m1) 个人。这种情况有 k 种。

最后考虑在一排 nn 个椅子里面放 mm 个人的方案数,相当于要找 (m + 1)(m+1) 个变量满足 x_1 \geq 0, x_{2, 3, \ldots, m} \geq k + 1, x_{m + 1} \geq 1x?1??0,x?2,3,,m??k+1,x?m+1??1 同时 x_1 + x_2 + \cdots + x_{m + 1} = nx?1??+x?2??+?+x?m+1??=n 的方案数。这个方案数就是 \binom{n - (m - 1)k}{m}(?m?n(m1)k??).

至于为什么是上述式子,其中 x_1x?1?? 表示的是 11 的下标,x_{2, 3, \ldots, m}x?2,3,,m?? 表示的是每个人离前一个人的距离,最后的 x_{m + 1}x?m+1?? 是松弛变量。可以加加减减让大家的限制都变成 \geq 11,就是熟悉的模型啦。

#include <map>#include <queue>#include <math.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>#include <iostream>using namespace std;long long a[1000005];const long long mod=1000000007;long long quick(long long a,long long b){    long long ans=1;    while(b)    {        if(b&1) {            ans=ans*a%mod;            b--;        }        b>>=1;        a=a*a%mod;    }    return ans;}int main(){    int T;    long long i,n,m,k;    a[1]=1;    for(i=2; i<=1000000; i++)        a[i]=(a[i-1]*i)%mod;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld",&n,&m,&k);        if(m==1)            printf("%lld\n",n);        else if(m+m*k>n)            printf("0\n");        else if(m+m*k==n)            printf("%lld\n",k+1);        else {            long long y=m-1;            long long x=n-m*k-1;            long long ans=a[x]*quick(a[x-y],mod-2)%mod*quick(a[y],mod-2)%mod;            printf("%lld\n",n*ans%mod*quick(m,mod-2)%mod);        }    }    return 0;}

 

HDU 5894 hannnnah_j’s Biological Test (组合数学) -2016 ICPC沈阳赛区网络赛