Problem B. Harvest of ApplesTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2671 Accepted Submission(s): 1045 Problem Description There are n apples on a tree, numbered from 1 to n .
Input The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Output For each test case, print an integer representing the number of ways modulo 109+7 .
Sample Input 2 5 2 1000 500
Sample Output 16 924129523
Source 2018 Multi-University Training Contest 4
Recommend chendu | We have carefully selected several similar problems for you: 6343 6342 6341 6340 6339 |
因为要求的是组合数的和,我们定义S(n,m)为C(n,0)~C(n,m)的累加和,然后可以推导出以下变换方程:
S(n+1, m) = 2S(n, m) - C(n, m) S(n-1, m) = (S(n, m) + C(n-1, m)) / 2
S(n, m+1) = S(n, m) + C(n, m+1) S(n, m-1) = S(n, m) - C(n, m)
下面两个是很容易看出来的,上面的两个则利用我们熟知的组合数递推方程C(n,m)=C(n-1,m-1)+C(n-1,m)可以推出
也就是说,如果我们已知S(n,m)就可以在O(1)的时间之内得到S(n-1,m),S(n+1,m),S(n,m-1),S(n,m+1),这看上去就跟区间操作一样了。所以用莫队算法即可,因为要求的是组合数,所以要预处理一下阶乘和逆元。复杂度为O(Tsqrt(MAX))
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+5;
ll fac[maxn],inv[maxn],ans[maxn],bl[maxn];
ll res,l,r;
struct mo
{
int l,r,id;
bool operator<(const mo &a)const
{
if(bl[l]==bl[a.l]) return r<a.r;
return l<a.l;
}
}q[maxn];
void init()
{
inv[0]=fac[0]=inv[1]=fac[1]=1;
for(int i=1;i<maxn;i++)
fac[i]=fac[i-1]*i%mod;
for(int i=2;i<maxn;i++)
inv[i]=(mod-(mod/i))*inv[mod%i]%mod;//lucas?????
for(int i=1;i<maxn;i++)
inv[i]=inv[i-1]*inv[i]%mod;
}
ll C(int n,int m)
{
ll res=fac[n]*inv[m]%mod;
res=res*inv[n-m]%mod;
return res;
}
void update(int x,int y)
{
if(x==1)
{
if(y==1)
res=(2*res-C(l,r)+mod)%mod;
else
res=(res+C(l-1,r))*inv[2]%mod;
}
else
{
if(y==1)
res=(res+C(l,r+1))%mod;
else res=(res-C(l,r)+mod)%mod;
}
}
int main()
{
int t;
init();
scanf("%d",&t);
int block=(int)sqrt(maxn);
int up=0;
for(int i=1;i<=t;i++)
{
scanf("%d %d",&q[i].l,&q[i].r);
q[i].id=i;
up=max(up,q[i].r);
}
for(int i=1;i<=up;i++)
{
bl[i]=(i-1)/block;
}
sort(q+1,q+t+1);
res=1;
l=0,r=0;
for(int i=1;i<=t;i++)
{
while(l<q[i].l) update(1,1),l++;
while(l>q[i].l) update(1,-1),l--;
while(r<q[i].r) update(-1,1) ,r++;
while(r>q[i].r) update(-1,-1) ,r--;
ans[q[i].id]=res;
}
for(int i=1;i<=t;i++)
printf("%lld\n",ans[i]);
}