BZOJ 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛

题目描述

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

输入

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

输出

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

样例输入

4 2

样例输出

6
样例说明
6种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡

提示

来源

Silver

思路

最多能放n/(k+1) 头公牛
如果n%(k+1)!=0 则能放n/(k+1)+1头,证明很简单。
我们从1到上界枚举可以放的公牛头数,放a头公牛需要(a-1)*k头母牛,因为牛是一样的所以用n减去(a-1)*k就是剩下的可以放公牛的位置数
则放a头公牛的方案数为
在这里插入图片描述

所以直接计算即可
**原文链接:https://blog.csdn.net/qq_43346903/article/details/82996920

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int Mod=5000011;

long long n,k,ans;

long long qpow(long long a,long long b) {
	long long ans=1;
	for(; b; b>>=1) {
		if(b&1)
			ans=ans*a%Mod;
		a=a*a%Mod;
	}
	return ans;
}

long long C(long long m,long long n) {
	long long sum1=1,sum2=1;
	if(m>n-m)
		m=n-m;
	for (long long i=1; i<=m; i++) {
		(sum1*=(n-i+1))%=Mod;
		(sum2*=i)%=Mod;
	}
	return (sum1*qpow(sum2,Mod-2))%Mod;
}

int main() {
	scanf("%lld%lld",&n,&k);
	long long maxn=n/(k+1);
	if(maxn*(k+1)!=n)
		maxn++;
	for(int i=1; i<=maxn; i++)
		ans=(ans%Mod+C(i,n-k*i+k)%Mod)%Mod;
	printf("%lld\n",(ans+1)%Mod);
	return 0;
}

 

posted @ 2019-08-08 00:14  双子最可爱啦  阅读(255)  评论(0编辑  收藏  举报