题目描述
约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛.牛们要站成一排.但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有K(O≤K<N)只牝牛.
请计算一共有多少种排队的方法.所有牡牛可以看成是相同的,所有牝牛也一样.答案对5000011取模
输入
一行,输入两个整数N和K.
输出
一个整数,表示排队的方法数.
样例输入
4 2
样例输出
6
样例说明
6种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡
样例说明
6种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡
提示
来源
思路
最多能放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;
}