HDU 6333 2018HDU多校赛 第四场 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): 989    Accepted Submission(s): 377

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

Output

For each test case, print an integer representing the number of ways modulo 10^9+7.

Sample Input

 

2

5 2

1000 500

Sample Output

 

16 924129523

Source

2018 Multi-University Training Contest 4

大致题意:一个组合数学裸题,直接求 \sum_{i=0}^{m} C_{n}^i 即可。

如果令s(n,m)=\sum_{i=0}^{m} C_{n}^i,可以得到关于s(n,m)的递推式:

\large S(n,m)=S(n,m-1)+C_{n}^{m}                         \large S(n,m)=S(n,m+1)-C_{n}^{m+1}

\large S(n,m)=2*S(n-1,m)-C_{n-1}^{m}              \large S(n,m)=\frac{S(n+1,m)+C(n,m)}{2}

由此,如果我们知道S(n,m),我们就可以知道在O(1)的时间复杂度内求出S(n+1,m)、S(n-1,m)、S(n,m+1)和S(n,m-1)这四个的数值。那么,我们把n和m看作区间询问的左右端点,对于读入的T个询问,我们完全可以按照莫队算法的区间移动的方式来解决这道题。O(1)转移已经给出,直接套用模板即可。时间复杂度\large O(T\sqrt{N})。具体见代码:

#include<bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define N 100010
using namespace std;

struct query{int l,r,block,id;} q[N<<2];
LL inv[N],fac[N],ans[N];
int blocks;

bool cmp(query a,query b)
{
    if (a.block!=b.block) return a.l<b.l;
    if (a.block&1) return a.r<b.r; return a.r>b.r;
}

void init()
{
    fac[1]=fac[0]=1;
    inv[1]=inv[0]=1;
    for(int i=2;i<N;i++)
    {
        fac[i]=fac[i-1]*i%mod;
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
    for(int i=2;i<N;i++)
        inv[i]=inv[i-1]*inv[i]%mod;
}

LL C(int x,int y)
{
    if (y>x) return 0;
    return fac[x]*inv[y]%mod*inv[x-y]%mod;
}

int main()
{
    init();
    IO;int T;cin>>T;
    blocks=sqrt(T)+1;
    for(int i=1;i<=T;i++)
    {
        int n,m;
        cin>>n>>m;
        q[i]=query{n,m,n/blocks,i};
    }
    sort(q+1,q+T+1,cmp);
    int l=1,r=0,res=1;
    for(int i=1;i<=T;i++)
    {
        while(l<q[i].l)
        {
            res=res*2%mod-C(l,r);
            if (res<0) res+=mod;
            l++;
        }
        while(l>q[i].l)
        {
            l--;
            res=(res+C(l,r))%mod*inv[2]%mod;
        }
        while(r<q[i].r)
        {
            r++;
            res=(res+C(l,r))%mod;
        }
        while(r>q[i].r)
        {
            res=(res-C(l,r)+mod)%mod;
            r--;
        }
        ans[q[i].id]=res;
    }
    for(int i=1;i<=T;i++)
        cout<<ans[i]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013534123/article/details/81352763
今日推荐