BZOJ 4403: 序列统计(lucas)

二次信任 提交于 2020-02-15 23:53:44

传送门

题目是给你m个数字,让你求1~n个数分别能构成的单调不降序列的个数的和且模一个1e6+3

对于这道题,我们先考虑n个人,然后我们把m个数字分给n个人,但是会有有人分不到的情况,所以我们假设每人都能分到

这样我们的总个数就变成了n+m个数字分给m个人,这样我们用隔板法能得到C(m-1,n+m-1)

然后总和就是n取1~n个组合数加起来,然而组合数有一个公式是C(m,n)=C(m,n-1)+C(m-1,n-1)

又由于C(m,m)=1,即C(m,1+m-1)=1,与C(m-1,m)合并后为C(m,m+1)

然后我们给整体总和的式子加1,化简就能得到C(m,n+m)-1

AC代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e6+3;
int fac[mod+10],ifac[mod+10],n,l,r,t;;
inline long long C(int n,int m) {
	if(m>n)return 0;
	return (fac[n]*ifac[fac[m]])%mod*ifac[fac[n-m]]%mod;
}
inline long long lucas(int n,int m) {
	if(!m)	return 1;
	return C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
signed main() {
	fac[0]=ifac[0]=ifac[1]=1;
	for (int i = 1; i <= mod; i++)
		fac[i] = fac[i - 1] * i % mod;
	for(int i = 2; i <= mod; i++)
		ifac[i] = (mod - mod/i) * ifac[mod % i] % mod;
	cin>>t;
	while(t--) {
		cin>>n>>l>>r;
		cout<<(lucas(n+r-l+1,r-l+1)%mod+mod-1)%mod<<'\n';
	}
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!