#组合计数,容斥定理#U136346 数星星

题目

天上的繁星一闪一闪的,甚是好看。你和你的小伙伴们一起坐在草地上,欣赏这美丽的夜景。
我们假定天上有\(n\)颗星星,它们排成一排,从左往右以此编号为1到\(n\),但是天上的星星实在太多了,你和你的小伙伴
们只能看到其中的\(k\)个星星,所以需要你在这\(n\)颗星星中选出\(k\)颗来进行观测,但是你的小伙伴给你提出了一个要求,
\(k\)颗星星中,至少存在\(r\)颗星星是连续的,连续是指这些星星的编号连续。


分析

考虑答案可以容斥实现,也就是

\[\large\sum_{i=1}^{\lfloor\frac{k}{r}\rfloor}(-1)^{i-1}\times C(n-k+1,i)\times C(n-ir,k-ir) \]

实质的过程就是在\(n-k+1\)个位置中选择\(i\)个位置插入长度至少为\(r\)的星星,

然后再在\(n-ir\)颗星星中选出\(k-ir\)颗星星,这样恰好选出\(k\)颗星星


代码

#include <cstdio>
#define rr register
using namespace std;
const int mod=1000000007,N=10000011;
int n,m,G,inv[N],fac[N],ans;
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline signed C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;} 
signed main(){
	fac[0]=fac[1]=inv[0]=inv[1]=1,scanf("%d%d%d",&n,&m,&G);
	for (rr int i=2;i<=n;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for (rr int i=2;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
	for (rr int i=1;i<=m/G;++i)
	    ans=mo(ans,1ll*((i&1)?1:(mod-1))*C(n-m+1,i)%mod*C(n-i*G,m-i*G)%mod);
	return !printf("%d",ans);
}
posted @ 2020-10-27 12:42  lemondinosaur  阅读(262)  评论(0编辑  收藏  举报