BZOJ_3398_[Usaco2009 Feb]Bullcow 牡牛和牝牛_组合数学

BZOJ_3398_[Usaco2009 Feb]Bullcow 牡牛和牝牛_组合数学

Description

    约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛.牛们要站成一排.但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有K(O≤K<N)只牝牛.
    请计算一共有多少种排队的方法.所有牡牛可以看成是相同的,所有牝牛也一样.答案对5000011取模

Input

一行,输入两个整数N和K.

Output

一个整数,表示排队的方法数.

Sample Input

4 2

Sample Output

6


 

枚举一个A牛的个数x,每两头A牛中间至少有K头B牛。

于是把这些必须放的减掉,就是一个挡板问题。

对答案的贡献是C[n-(x-1)*k][x]。

 

代码:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mod 5000011
typedef long long ll;
#define N 100050
ll qp(ll x,ll y) {
    ll re=1; for(;y;y>>=1ll,x=x*x%mod) if(y&1ll) re=re*x%mod; return re;
}
ll fac[N],inv[N];
int n,K;
void init() {
    int i=0;
    for(fac[0]=1,i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
    inv[n]=qp(fac[n],mod-2);
    for(i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(int x,int y) {
    if(x<y) return 0;
    return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main() {
    scanf("%d%d",&n,&K);
    init();
    int i;
    ll ans=0;
    for(i=1;n-(i-1)*K>=i;i++) {
        (ans+=C(n-(i-1)*K,i))%=mod;
    }
    printf("%lld\n",(ans+1)%mod);
}

 

posted @ 2018-05-23 20:05  fcwww  阅读(179)  评论(0编辑  收藏  举报