Problem B. Harvest of Apples
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 608 Accepted Submission(s): 212
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 Input
2 5 2 1000 500
Sample Output
16 924129523
Source
2018 Multi-University Training Contest 4
挺丢人的,我做的时候一直以为这只是个纯数学题。。。。。。然后卡了4个小时- =
令s(n,m)为答案,打表/推导可得 s(n,m)=s(n-1,m-1)+s(n-1,m)
有了这个式子,意味着对于一个(n,m) 在已知s(n,m)的情况下,s(n,m+1)和s(n+1,m)是可以O(1)求得的
s(n+1,m)=s(n-1,m-1)+s(n-1,m)=2*s(n-1,m)-C(n-1,m)
s(n,m+1)=s(n,m)+c(n,m+1)
那么,就可以套上莫队搞了。
#include<bits/stdc++.h>
#define mp make_pair
#define fir first
#define se second
#define ll long long
#define pb push_back
using namespace std;
const int maxn=1e5+10;
const ll mod=1e9+7;
const int maxm=1e6+10;
const double eps=1e-7;
const int inf=0x3f3f3f3f;
const double pi = acos(-1.0);
ll qpow(ll a,ll b,ll p)
{
ll res=1;
while (b)
{
if(b&1) res=res*a%p;
b>>=1;
a=a*a%p;
}
return res;
}
ll fac[maxn],facinv[maxn];
void init()
{
fac[0]=fac[1]=facinv[0]=facinv[1]=1;
for (int i=2; i<maxn; i++)
{
fac[i]=fac[i-1]*i%mod;
}
facinv[100000]=qpow(fac[100000],mod-2,mod);
for (int i=100000-1;i>=2;i--){
facinv[i]=(facinv[i+1]*(i+1))%mod;
}
}
ll c(int n,int m)
{
if (m<0) return 0;
if (n<m) return 0;
return fac[n]*facinv[m]%mod*facinv[n-m]%mod;
}
;
int n, m, k;
int pos[maxn];
long long cnt[maxn];
long long ans[maxn], tmp[maxn];
struct node
{
int l, r, id;
bool operator < ( const node &a) const
{
if (pos[l]==pos[a.l]){
return r<a.r;
}
return l<a.l ;
}
} p[maxn];
int a[maxn];
ll inv2=(mod+1)/2;
long long cur;
void add (int l, int pos)
{
cur+=c(l,pos);
cur=(cur)%mod;
}
void del (int l, int pos)
{
cur+=mod-c(l,pos);
cur%=mod;
}
void add1(int l,int r){
cur=cur+cur+mod-c(l,r);
cur=cur%mod;
// cout<<"cur1="<<cur<<endl;
// cout<<"l="<<l<<" r="<<r<<endl;
}
void del1(int l,int r){
cur=(cur+c(l,r))%mod;
// cout<<"cur1="<<cur<<endl;
cur=cur*inv2%mod;
// cout<<"cur2="<<cur<<endl;
}
int flag[maxn];
ll two[maxn];
namespace fastIO
{
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc()
{
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf +
BUF_SIZE;
if(p1 == pend)
{
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1)
{
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank( char ch)
{
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' ;
}
inline void read( int &x)
{
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0' ; (ch = nc()) >= '0' && ch <= '9' ; x = x * 10 +
ch - '0' );
}
#undef BUF_SIZE
};
int main ()
{
//freopen("b.in","r",stdin);
int t;
scanf("%d",&t);
//fastIO::read(t);
init();
two[0]=1;
int block = ceil ( sqrt (100000*1.0));
for ( int i = 1; i <= 100000; i++) pos[i] = (i)/block;
for (int i=1;i<=t;i++){
/*::read(p[i].l);
fastIO::read(p[i].r);*/
scanf ( "%d%d", &p[i].l, &p[i].r);
p[i].id = i;
}
sort (p+1, p+t+1);
int l = 1, r = 0;
cur = 1;
for ( int i = 1; i <= t; i++)
{
/*if (pos[p[i].l]!=pre){
pre=pos[p[i].l];
l=p[i].l;
r=0;
cur=1;
}*/
//cout<<"i="<<i<<endl;
while (l < p[i].l)
{
cur=cur+cur+mod-c(l,r);
cur=cur%mod;
l++;
}
while(l>p[i].l){
l--;
del1(l,r);
}
while (r < p[i].r)
{
r++;
cur+=c(l,r);
cur=(cur)%mod;
}
while (r > p[i].r)
{
cur+=mod-c(l,r);
cur%=mod;
r--;
}
// cout<<"cur="<<cur<<endl<<endl;
ans[p[i].id] = cur;
}
for (int i=1;i<=t;i++){
printf("%lld\n",ans[i]);
}
return 0;
}