HDU 6333 2018 Multi-University Training Contest 4 :Problem B. Harvest of Apples

莫队很简单
只要找到递推式就好办,递推式:T(n+1,m)=2*T(n,m)-C(n,m)
T(n,m)=C(n,0)+C(n,1)+C(n,2)+…+C(n,m)
再根据C(n+1,m)=C(n,m)+C(n,m-1)可得到递推式
代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long ll;
const int maxn=100000+100;
const ll mod=1e9+7;

int R[maxn];
struct Mo{

    int n,m;
    int id;
}mo[maxn];


ll Ans[maxn];
ll inv[maxn];
ll fac[maxn];
ll key;
int nn,mm;

inline bool cmp(Mo a,Mo b){

    return R[a.n]==R[b.n]?a.m<b.m:R[a.n]<R[b.n];
}

ll mypow(ll a,ll b){

    ll sum=1;
    while(b){

        if(b&1) sum=sum*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return sum;
}

void init(){

    fac[0]=fac[1]=1;
    for(int i=2;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
    inv[maxn-1]=mypow(fac[maxn-1],mod-2);
    for(int i=maxn-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}

ll C(int a,int b){

    return fac[a]*inv[b]%mod*inv[a-b]%mod;
}

void addn(){

    key=(key*2%mod-C(nn,mm))%mod;
}

void deln(){

    key=(key+C(nn-1,mm))%mod*inv[2]%mod;
}

void addm(){

    key=(key+C(nn,mm+1))%mod;
}

void delm(){

    key=(key-C(nn,mm))%mod;
}

int main(){

    init();
    int m;
    scanf("%d",&m);
    int size=sqrt(100000.0);
    for(int i=1;i<=100000;i++) R[i]=i/size;
    for(int i=1;i<=m;i++) scanf("%d%d",&mo[i].n,&mo[i].m),mo[i].id=i;
    sort(mo+1,mo+1+m,cmp);
    nn=1,mm=0;
    key=1;
    for(int i=1;i<=m;i++){

        while(nn<mo[i].n) addn(),nn++;
        while(mm<mo[i].m) addm(),mm++;
        while(nn>mo[i].n) deln(),nn--;
        while(mm>mo[i].m) delm(),mm--;

        Ans[mo[i].id]=(key+mod)%mod;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",Ans[i]); 
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81352836