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

 

题目大概:

给出T组数据,每组数据一个n 和一个 m,计算C(n,0)+C(n,1)+.....+C(n,m),%1e9+7。

思路:

刚开始很容易想到分块,发现是离线询问,指针的跳动也可以O(1)实现,那么就可以用莫队解决。

这是杨辉三角,杨辉三角的前缀和,可以推出前一项和后一项的关系,毕竟是前缀和,比较容易推。

直接预处理,分块莫队就行了。

代码:

#include <bits/stdc++.h>

using namespace std;
#define ll long long
const int maxn=1e5+100;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
int fac[maxn],inv[maxn],be[maxn],ans[maxn];
int inv2;
struct poin
{
    int n,m,id;
} G[maxn];
bool cmp(const poin &a,const poin &b)
{
    if(be[a.n]==be[b.n])return a.m<b.m;
    else return a.n<b.n;
}
long long pow_mod(long long a,long long b,long long m)
{
    a=a%m;
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%m;
            b--;
        }
        b>>=1;
        a=a*a%m;
    }
    return ans;
}
ll C(int n,int m)
{
    return (1LL*fac[n]*inv[m]%mod*inv[n-m])%mod;
}
void init()
{
    int mx=100000;
    fac[0]=1;
    for(int i=1; i<=mx; i++)
    {
        fac[i]=(1LL*fac[i-1]*i)%mod;
    }
    inv2=pow_mod(2,mod-2,mod);
    inv[mx]=pow_mod(fac[mx],mod-2,mod);
    for(int i=mx-1; ~i; i--)inv[i]=(1LL*inv[i+1]*(i+1))%mod;
    int block=sqrt(mx);
    for(int i=1; i<=mx; i++)
    {
        be[i]=i/block;
    }
}

int main()
{
    int T;
    init();
    scanf("%d",&T);
    for(int i=1; i<=T; i++)
    {
        scanf("%d%d",&G[i].n,&G[i].m);
        G[i].id=i;
    }
    sort(G+1,G+1+T,cmp);
    int n=1,m=1;
    int sum=2;
    for(int i=1; i<=T; i++)
    {
        while(n<G[i].n)sum=( 0LL + 2*sum + mod - C(n++,m)) % mod;
        while(n>G[i].n)sum= ( sum + C(--n, m)) % mod * inv2 % mod;
        while(m<G[i].m) sum =(sum + C(n, ++m )) % mod;
        while(m>G[i].m)sum =(sum + mod - C(n, m-- )) % mod;
        ans[G[i].id]=sum;

    }
    for(int i=1;i<=T;i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1046765624/article/details/81353882