BZOJ 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛
题目描述
约翰要带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; }