【Usaco 2009 Feb】Bullcow 牡牛和牝牛

【题目】

传送门

Description

约翰要带 n ( 1 ≤ n ≤ 100000 ) n(1≤n≤100000) n(1n100000) 只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛。牛们要站成一排。但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有 k ( 0 ≤ k < n ) k(0≤k<n) k(0k<n) 只牝牛。

请计算一共有多少种排队的方法。所有牡牛可以看成是相同的,所有牝牛也一样。答案对 5000011 5000011 5000011 取模。

Input

一行,输入两个整数 n n n k k k

Output

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

Sample Input

4 2

Sample Output

6

HINT

6 6 6 种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡


【分析】

牡( m u ˇ mǔ muˇ)牛,公牛的意思,牝( p ı ˋ n pìn pıˋn)牛,母牛的意思

好啦这不是这道题的重点,重点是这道题的算法

不难发现,如果有 x x x 头牡牛,一定会有 ( x − 1 ) ⋅ k (x-1)\cdot k (x1)k 头牝牛,也就是说牡牛只能在剩下的 n − ( x − 1 ) ⋅ k n-(x-1)\cdot k n(x1)k 个位置上选,方案数就是 C n − ( x − 1 ) ⋅ k                x C^{\;\;\;\;\;\;\;x}_{n-(x-1)\cdot k} Cn(x1)kx

那么循环枚举有多少个牡牛,按公式计算答案后累加,到 x > n − ( x − 1 ) ⋅ k x>n-(x-1)\cdot k x>n(x1)k 退出就可以了

最后吐槽一下,数据范围是不是有误啊,数组开小导致 WA 了好久


【代码】

#include
#include
#include
#define N 1000005
#define Mod 5000011
using namespace std;
int fac[N],inv[N];
int Power(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1)
		  ans=1ll*ans*a%Mod;
		a=1ll*a*a%Mod;
		b>>=1;
	}
	return ans;
}
void prework()
{
	int i;
	fac[0]=fac[1]=1;
	for(i=2;i<N;++i)  fac[i]=1ll*fac[i-1]*i%Mod;
	inv[N-1]=Power(fac[N-1],Mod-2);
	for(i=N-2;~i;--i)  inv[i]=1ll*inv[i+1]*(i+1)%Mod;
}
int C(int n,int m)
{
	return 1ll*fac[n]*inv[m]%Mod*inv[n-m]%Mod;
}
int main()
{
	prework();
	int n,k,i,num,ans=1;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;++i)
	{
		num=n-(i-1)*k;
		if(i>num)  break;
		ans=(ans+C(num,i))%Mod;
	}
	printf("%d",ans);
	return 0;
}

你可能感兴趣的:(#,排列组合)