HDU 6333 Problem B. Harvest of Apples 莫队.....

/**
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333

题意:n个不相同的数取最多为m的取法数;

NTT  多了一个log  好像直接测就T了  
赛后了解正解为莫队时  G++;

**********tricks****
a[i].r a[i].1 输入. 分析组合数的l r 与 n m的状态转移关系;
确定初始l r 值;
*/


#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=1e5+5;
const int mod=1e9+7;

ll fac[maxn],inv[maxn];

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;
}

ll C(int n,int k){ return fac[n]*inv[k]%mod *inv[n-k]%mod;}

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

int pos[maxn];

struct node{
    int l,r,id;
    bool operator <(const node& a) const{
        if(pos[l]==pos[a.l]) return r<a.r;
        return pos[l]<pos[a.l];
    }
}a[maxn];
ll ans[maxn];

int main(){
    init();
    ll inv2=qpow(2,mod-2);
    int m=sqrt(maxn);
    int t;scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d %d",&a[i].r,&a[i].l);
        pos[i]=(i-1)/m+1;
        a[i].id=i;
    }
    sort(a+1,a+t+1);
    ll res=1;
    int l=1,r=0;
    //  m   n
    for(int i=1;i<=t;i++){
        while(r<a[i].r) {
            res=(2*res%mod-C(r,l)+mod)%mod;//s(n+1,m)=2*s(n,m)-c(n,m); 由于得保证C(n,m)的n大于等于m  因此这题应该先扩大r的区间
            r++;
        }
        while(l>a[i].l){
            res=(res-C(r,l)+mod)%mod;//s(n,m-1)=s(n,m)-c(n,m);
            l--;
        }
        while(l<a[i].l){
            res=(res+C(r,l+1))%mod;//s(n,m+1)=s(n,m)+c(n,m+1);
            l++;
        }
        while(r>a[i].r) {
            res=((res+C(r-1,l))%mod)*inv2%mod;//s(n-1,m)=1/2*(s(n,m)+c(n-1,m));
            r--;
        }
        ans[a[i].id]=res;
    }
    for(int i=1;i<=t;i++) printf("%lld\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/81354894