hdu6333 Problem B. Harvest of Apples(组合数+莫队)

hdu6333 Problem B. Harvest of Apples

题目传送门

题意:

求(0,n)~(m,n)组合数之和

题解:

C(n,m)=C(n-1,m-1)+C(n-1,m)   
设 S(n,m)=C(n,0)+C(n,1)+C(n,2)+。。。+C(n,m)
然后将S(n,m) 通过 第一个公式 拆项
最后化简 变为 S(n,m)=2*S(n-1,m)-C(n-1,m);
即:
所以可以离线用莫队算法
参考博客:链接1链接2

代码:

 

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;

/********组合数模板*********/
ll pow_mod(ll a, ll b) {
    ll res = 1ll; a %= mod;
    while(b){
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    } return res;
}
ll inv(ll a) { return pow_mod(a, mod-2); }
ll F[N], Finv[N];//F是阶乘,Finv是逆元的阶乘
void init() {
    F[0] = Finv[0] = 1ll;
    for(int i = 1; i < N; i ++){
        F[i] = F[i-1] * 1ll * (ll)i % mod;
        Finv[i] = Finv[i-1] * 1LL * inv(i) % mod;
    }
} // O(n)预处理
ll C(ll n, ll m) {
    if(m < 0 || m > n) return 0;
    return F[n] * 1LL * Finv[n - m] % mod * Finv[m] % mod;
} // O(1)获得组合数C(n,m)
/**************************/

int block[N];
ll res[N];
struct mo
{
    int n,m;
    int id,block;
    bool operator < (const mo &p) const{
      if(block==p.block) return n<p.n;
      else return block<p.block;
    }
}s[N];
int main()
{
    int T;
    scanf("%d",&T);
    int len=sqrt(N+0.5);
    for(int i=0;i<T;i++)
    {
        scanf("%d %d",&s[i].n,&s[i].m);
        s[i].block=s[i].m/len;s[i].id=i;
    }
    sort(s,s+T);
    ll ans=1;
    init();
    int L=0,R=0;
    for(int i=0;i<T;i++)
    {
        int l=s[i].n,r=s[i].m;
        while(L>l) ans=((ans+C(L-1LL,R))%mod*Finv[2])%mod, L--;
        while(L<l) ans=(2*ans%mod-C(L,R)+mod)%mod, L++;
        while(R<r) ans=(ans+C(L,R+1))%mod, R++;
        while(R>r) ans=(ans-C(L,R)+mod)%mod, R--;
        res[s[i].id]=ans;
    }
    for(int i=0;i<T;i++)
        printf("%lld\n",res[i]);
    return 0;
}
View Code

 

posted @ 2019-02-16 16:00  better46  阅读(258)  评论(0编辑  收藏  举报