牛客月赛17-计数-(组合数+球盒问题)

60 篇文章 1 订阅

J

题意:
给你一个数组,这个数组是单调不增的,但是有些位置的数丢失了,现在问你合法的数组一共有多少个,对1e9+7取模。同时数组中的每个数都是1到1000。

思考:
刚开始看着像dp,感觉不太好做,其实呢主要是还是对球和盒子问题不太熟悉。这个题就是球和盒子问题,比如9 0 0 7,那么可以放的数是9 8 7,一共3个,然后有两个0也就是2个球,那么就是2个求放到3个盒子里,盒子可以空,问你有多少种放法。这就是球和盒子的经典问题C(n+m-1,m-1)。球和盒子经典问题
代码:

int T,n,m,k;
int va[N];

int fact[N],infact[N];

int ksm(int a,int b)
{
	int sum = 1;
	while(b)
	{
		if(b&1) sum = sum*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return sum;
}

void init(int x)
{
	fact[0] = infact[0] = 1;
	for(int i=1;i<=x;i++) fact[i] = fact[i-1]*i%mod;
	infact[x] = ksm(fact[x],mod-2)%mod; //注意这里,这样求infact会少很多ksm,时间会更快
	for(int i=x-1;i>=1;i--) infact[i] = infact[i+1]*(i+1)%mod;
}

int C(int a,int b)
{
	if(a<b) return 0;
	return fact[a]*infact[b]%mod*infact[a-b]%mod;
}

signed main()
{
	IOS;
	init(1e6+2000);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>va[i];
	va[n+1] = 1;
	int l = 1000,res = 0,ans = 1;
	for(int i=1;i<=n+1;i++)
	{
		if(va[i]==0)
		{
			res++;
			continue;
		}
		int can = l-va[i]+1;
		ans = ans*C(can+res-1,can-1)%mod;
		l = va[i];
		res = 0;
	}
	cout<<ans%mod;
	return 0;
}

总结:
多多思考和总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值