首页 > 其他分享 >牡牛和牝牛

牡牛和牝牛

时间:2024-04-14 09:33:17浏览次数:15  
标签:ll inv 牝牛 ans 牡牛 公牛

原题来自:USACO 2009 Feb. Silver

牡 mǔ,畜父也。牝 pìn,畜母也。 ——《说文解字》

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

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

输入格式
一行,输入两个整数 n和 k。
(1<=n<=1e5,0<k<n)
输出格式
一个整数,表示排队的方法数。
样例输入

4 2

样例输出

6

通过枚举公牛的数量i,可以求出公牛间的空隙数为n-1,进而求出所需母牛的数量(n-1)* k,再求出实际存在的公牛的数量n-(i-1)* k,如果实际存在的数量大于枚举量,说明容纳不了这么多
还有一个问题,因为模数比范围大,所以不需要lucas,仅用排列组合就行了(感觉lucas这个东西跟快读快写似的,多数是为了存__int128,而不是加速)
还有一个问题,要算上没有公牛的情况,很简单,+1就行,如果想从0开始枚举记得开大点数组,因为n+k>n

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int p=5000011;
typedef long long ll;
ll n,k;
ll sum;
ll fact[120000],inv[120002];
ll C(ll n,ll m,ll p){
	return (fact[n]*inv[m]%p*inv[n-m]%p)%p;
}
ll qpow(ll n,ll m,ll p){
	ll ans=1;
	while(m){
		if(m&1) ans=ans*n%p;
		n=n*n%p;
		m>>=1;
	}
	return ans;
}
int main(){
	cin>>n>>k;
	fact[0]=1;inv[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=fact[i-1]*i%p;
		inv[i]=qpow(fact[i],p-2,p);
	}
	for(int i=1;i<=n;i++){
		int j=n-(i-1)*k;
		if(j<i) continue;
		sum+=C(j,i,p);
		sum%=p;
	}
	cout<<sum+1;
}

标签:ll,inv,牝牛,ans,牡牛,公牛
From: https://www.cnblogs.com/PeppaEvenPigShiGeNiuBDePig/p/18133763

相关文章

  • 牡牛和牝牛
    牡牛和牝牛约翰要带$N$只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛。牛们要站成一排,但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少......