HDU 6333 Harvest of Apples 【莫队】【逆元线性筛】

Problem B. Harvest of Apples

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2017    Accepted Submission(s): 784


 

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≤mn≤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

预处理逆元参考文章:链接

#include
using namespace std;
#define ll long long
const int Mod = 1e9 + 7;
const int MAX = 1e5 + 7;
int sz;
struct node{
    int l, r, id;
    bool operator < (const node &a) const{
        if(l / sz == a.l / sz) return r < a.r;
        return l < a.l;
    }
} a[MAX];
ll res[MAX], ans = 1;
ll fac[MAX], inv[MAX];
ll qpow(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b & 1) ans = (ans * a) % Mod;
        b >>= 1;
        a = (a * a) % Mod;
    }
    return ans;
}
void init(){
    fac[1] = fac[0] = 1;
    for(int i = 2; i <= MAX; i++) fac[i] = fac[i - 1] * i % Mod;
    inv[MAX] = qpow(fac[MAX], Mod - 2);
    for(int i = MAX - 1; i >= 0; i--)
        inv[i] = (inv[i + 1] * (i + 1)) % Mod;
}
ll cnm(ll x, ll y){
    return fac[x] * inv[y] % Mod * inv[x - y] % Mod;
}
void del(int l, int r, int flag){
    if(flag)
        ans = (ans * 2 % Mod - cnm(l, r) + Mod) % Mod;
    else
        ans = (ans - cnm(l, r) + Mod) % Mod;
}
void add(int l, int r, int flag){
    if(flag)
        ans = (ans + cnm(l, r)) % Mod * inv[2] % Mod;
    else
        ans = (ans + cnm(l, r)) % Mod;
}
int main(){
    int n;
    init();
    scanf("%d", &n);
    sz = sqrt(n);
    for(int i = 1; i <= n; i++){
        scanf("%d%d", &a[i].l, &a[i].r);
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n);
    int p = 1, q = 0;
    for(int i = 1; i <= n; i++){
        int L = a[i].l;
        int R = a[i].r;
        while(p < L){
            del(p, q, 1);
            p++;
        }
        while(p > L){
            add(p - 1, q, 1);
            p--;
        }
        while(q < R){
            q++;
            add(p, q, 0);
        }
        while(q > R){
            del(p, q, 0);
            q--;
        }
        res[a[i].id] = ans;
    }
    for(int i = 1; i <= n; i++) printf("%lld\n", res[i]);
    return 0;
}

 

你可能感兴趣的:(莫队)