Problem B. Harvest of Apples
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2203 Accepted Submission(s): 858
Problem Description
There are n apples on a tree, numbered from 1 to n.
Count the number of ways to pick at most m apples.
Input
The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤105).
Output
For each test case, print an integer representing the number of ways modulo 109+7.
Sample Iput
2 5 2
1000 500
Sample Output
16
924129523
题目:
给出T组n和m(1<=T<=1e5, 1<=m<=n<=1e5)。
求
思路:
首先看测试数据很大,所以求解S(n,m)的时间复杂度绝对小于O(n),如果每个测试用例独立的计算肯定是超时的
所以应该想到离线来计算,用到莫队算法,这时候就要把他想成一个区间了,并且要退出区间左右移动的转移式
S(l,r)=S(l,r+1)-C(l,r+1)
=S(l,r-1)+C(l,r);
=2*S(l-1,r)-C(l-1,r) (由杨辉三角得出)
=(S(l+1,r)+C(l,r))/2;
get1:
ans=((ans+comb(--L,R))/2.0)mod; ×
ans=((ans+comb(--L,R))*inv[2])%mod; √
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <iostream>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const int N = 1e5+7;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 7;
struct node
{
int l,r,id;
}p[N];
int F[N], Finv[N], inv[N];
int unit;
ll res[N];
void init(){
F[0] = Finv[0] = inv[1] = 1;
for (register int i = 2; i < N; i++)
inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod;
for (register int i = 1; i < N; i++){
F[i] = F[i - 1] * 1ll * i % mod;
Finv[i] = Finv[i - 1] * 1ll * inv[i] % mod;
}
}
int comb(int n, int m){///comb(n, m)¾ÍÊÇC(n, m)
if (m < 0 || m > n) return 0;
return F[n] * 1ll * Finv[n - m] % mod * Finv[m] % mod;
}
bool cmp(node a,node b)
{
if(a.l/unit!=b.l/unit) return a.l<b.l;
return a.r<b.r;
}
int main()
{
int t,i,L,R;
ll ans;
init();
scanf("%d",&t);
unit=sqrt(maxn);
for(i=1;i<=t;i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p+1,p+1+t,cmp);
L=1;R=0;
ans=1;
for(i=1;i<=t;i++)
{
while(L<p[i].l) ans=(2*ans-comb(L++,R)+mod)%mod;
while(L>p[i].l) ans=((ans+comb(--L,R))*inv[2])%mod;
while(R<p[i].r) ans=(ans+comb(L,++R))%mod;
while(R>p[i].r) ans=(ans-comb(L,R--)+mod)%mod;
res[p[i].id]=ans;
}
for(i=1;i<=t;i++) printf("%I64d\n",res[i]);
return 0;
}
/*
S(l,r)=S(l,r+1)-C(l,r+1) ->S(l,r+1)=S(l,r)+C(l,r+1)
=S(l,r-1)+C(l,r); ->S(l,r-1)=S(l,r)-C(l,r)
=2*S(l-1,r)-C(l-1,r) ->S(l-1,r)=(S(l,r)+C(l-1,r))/2
=(S(l+1,r)+C(l,r))/2; ->S(l+1,r)=2*S(l,r)-C(l,r)
*/