HDU - 6333 Problem B. Harvest of Apples (莫队+组合数学+重要公式)

题链:https://vjudge.net/problem/HDU-6333

题意:给出n,m,求\sum_{i=0}^{m} C_{n}^{m}

思路:首先,题目保证m<=n,我们考虑把m看成l,n看成r。那么,问题就转化为了莫队解决的区间问题。首先我们定义 S(n,m) = \sum_{i=0}^{m} C_{n}^{i}

现在考虑添加删除操作。对于l的移动我们可以轻松的解决。

l<ql时,S(r,l+1)=S(r,l)+C_{r}^{l+1}

l>ql时,S(r,l)=S(r,l+1)-C_{r}^{l+1}

但是对于r的移动,我们就要推一下了,我们知道组合公式可以根据杨辉三角计算,C_{n}^{m} = C_{n-1}^{m} + C_{n-1}^{m-1}

S(r+1,l) \\= C_{r+1}^{0} + C_{r+1}^{1} + ... + C_{r+1}^{l} \\=(0+C_{r}^{0}) + (C_{r}^{0}+C_{r}^{1}) + (C_{r}^{1}+C_{r}^{2}) + ... + (C_{r}^{l-1}+C_{r}^{l}) \\=(C_{r}^{0}+C_{r}^{0}) + (C_{r}^{1}+C_{r}^{1}) + ... + (C_{r}^{l-1}+C_{r}^{l-1}) +(C_{r}^{l}+C_{r}^{l})-C_{r}^{l} \\= 2S(r,l)-C_{r}^{l}

那么我们现在解决r的移动了。

r<qr时,S(r+1,l)=2S(r,l)-C_{r}^{l}

r>qr时,S(r,l)=(S(r+1,l)-C_{r}^{l})/2


我们都知道阶乘可以O(n)的时间通过递推式n!=(n-1)! * n来推出,其实在数论中阶乘的逆元也是可以用递推式inv((n-1)!) \equiv inv(n!) * n \quad mod\quad p来推出的,稍微证明一下:

我们设n!的逆元表示为[n!]^{-1},现在我们要求(n-1)!的逆元,我们可以考虑将(n-1)!乘上一个n变为n!

  (n!)*[n!]^{-1} \equiv 1 \quad mod \quad p \\ \Rightarrow ((n-1)!*n)*[n!]^{-1} \equiv 1 \quad mod \quad p \\ \Rightarrow (n-1)! *(n*[n!]^{-1}) \equiv 1 \quad mod \quad p \\ \Rightarrow (n-1)! *([n!]^{-1}*n) \equiv 1 \quad mod \quad p \\ \Rightarrow (n-1)! *[(n-1)!]^{-1} \equiv 1 \quad mod \quad p \\ \Rightarrow [(n-1)!]^{-1} \equiv [n!]^{-1}*n \quad mod \quad p

inv((n-1)!) \equiv inv(n!) * n \quad mod\quad p得证


注意:

1、C_{n}^{m} = 0 \quad when \quad m>n

2、初值l=1 , r=1 ; sum=2

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9+7;
const int N = 1e5+10;
ll f[N],in[N],in2,ans[N],sum;
struct node{
	int l,r,id;
}q[N];
int n,block,be[N];
ll poww(ll a, ll b){
	ll ans=1;
	while(b){
		if(b&1) ans=(ans*a)%mod; 
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
bool cmp(node a,node b){
	return (be[a.l]^be[b.l]) ? be[a.l]<be[b.l] : (be[a.l]&1) ? a.r<b.r : a.r>b.r;
}
ll C(int n,int m){
	return n<m ? 0LL : f[n]*in[m]%mod*in[n-m]%mod;
}
int main(void){
	block=ceil(sqrt(N));
	in[0]=f[0]=1;
	for(int i=1;i<N;i++)
		f[i]=f[i-1]*i%mod,be[i]=i/block;		
	in[N-1]=poww(f[N-1],mod-2);
	in2=poww(2LL,mod-2);
	for(int i=N-2;i>=1;i--)
		in[i]=in[i+1]*(i+1)%mod;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&q[i].r,&q[i].l),q[i].id=i;
	sort(q+1,q+1+n,cmp);
	int l=1,r=1;
	sum=2;
	for(int i=1;i<=n;i++){
		int ql=q[i].l,qr=q[i].r;
		while(l<ql) sum=(sum+C(r,++l))%mod;
		while(l>ql) sum=(sum-C(r,l--)+mod)%mod;
		while(r<qr) sum=(2*sum%mod-C(r++,l)+mod)%mod;
		while(r>qr) sum=((sum+C(--r,l))%mod*in2)%mod;
		ans[q[i].id]=sum;
	}	
	for(int i=1;i<=n;i++)
		printf("%lld\n",ans[i]);
	return 0;	
} 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值