[HDU](6333)Problem B. Harvest of Apples ---- 数论+莫队算法

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≤1e5) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤1e5).
 

Output


For each test case, print an integer representing the number of ways modulo 1e9+7.
 

Sample Input

2
5 2
1000 500
 

Sample Output


16
924129523
 

Source


2018 Multi-University Training Contest 4

题意:让你求 \sum C(n,i)   范围:i属于[0,m]     我们把左边式子简称为S(n,m)

2000ms的时限 O(T*m)的复杂度无法按正常的求和做。

所以根据这个题的特性,离线查询,可以使用莫队算法。(打比赛时,QAQ太菜了,学的东西还是太少了)

我们根据组合数的公式,可以推出以下公式:

S(n,m) = S(n,m-1)+C(n,m)

S(n,m) = 2*S(n-1,m)-C(n-1,m)

S(n,m+1) = S(n,m)+C(n,m+1)

S(n+1,m) = 2*S(n,m)-C(n,m)

这样我们就可以找到区间S(n+1,m),S(n-1,m),S(n,m+1),S(n,m-1) 

酱紫就可以利用莫队分块了

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
const int mod = 1e9+7;
struct query{
    int l;
    int r;
    int id;
};
query e[maxn];
ll ans[maxn];
ll inv[maxn],fac[maxn];
int block;//分块数
int pos[maxn];
int curL = 1;
int curR = 1;
ll now;
ll inv2;
ll qpow(ll a,int p)
{
    ll tmp = 1;
    while(p){
        if(1&p) tmp = (tmp*a)%mod;
        a = (a*a)%mod;
        p>>=1;
    }
    return tmp;
}
void init()
{
    fac[0] = 1;
    for(int i=1;i<=maxn;i++)
        fac[i] = (fac[i-1]*i)%mod;
    inv[maxn] = qpow(fac[maxn],mod-2);
    inv2 = qpow(2,mod-2);
    for(int i=maxn;i>=1;i--)
        inv[i-1] = (inv[i]*i)%mod;
}
ll comb(int n,int m)
{
    if(m<0 || m>n) return 0;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
bool cmp(query a,query b)
{
    return (pos[a.l] == pos[b.l])?a.r<b.r:a.l<b.l;
}
inline void addN(int posL,int posR) //S(n-1,m)时
{
    now = (2*now-comb(posL-1,posR)+mod)%mod;
}
inline void addM(int posL,int posR)//S(n,m-1)时
{
    now = (now+comb(posL,posR))%mod;
}
inline void delN(int posL,int posR)//S(n+1,m)时
{
    now = (now+comb(posL-1,posR))%mod*inv2 %mod;
}
inline void delM(int posL,int posR)//S(n,m+1)时
{
    now = (now-comb(posL,posR)+mod)%mod;
}
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif // LOCAL_FILE
    int t;
    init();
    block = (int)sqrt(maxn);
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%d %d",&e[i].l,&e[i].r);
        e[i].id = i;
        pos[i] = i/block;//**
    }
    sort(e+1,e+t+1,cmp);
    now = 2;//curL = curR = 1;s(1,1) = 2;
    for(int i=1;i<=t;i++)
    {
        int L = e[i].l;
        int R = e[i].r;
        while(curL<L) addN(++curL,curR);
        while(curR<R) addM(curL,++curR);
        while(curL>L) delN(curL--,curR);
        while(curR>R) delM(curL,curR--);
        ans[e[i].id] = now;
    }
    for(int i=1;i<=t;i++)
    {
        printf("%I64d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/81395457
今日推荐