HDU6333 - 莫队算法

Harvest of Apples

题目大意

给你n,m求i=0mCni%(109+7)

数据范围

T组数据T105,1m,n105

解题思路

这题常规思路暴力求前缀和时间复杂度和空间复杂度都是显然不够的,所以,采用莫队算法将T个询问排序,之后将m看做l,n看做r,通过观察可以发现

i=0mCni=2i=0mCn1iCn1m

所以首先将r加/减到指定行,之后对l进行加/减,设res为答案,即:

r加的时候:res=res2Crl,r++;

r减的时候:r,res=(res+Crl)/2;

l加的时候:l++,res=res+Crl;

l减的时候:res=resCrl,l;

具体见代码:

AC代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100000;
const int Pt = 1e9 + 7;
struct NOOD {
    int l, r, id;
}q[maxn + 5];
LL P[maxn + 5], rP[maxn + 5];
int T;
int B[maxn + 5];
LL qwe(LL x, LL y) {
    LL res = 1;
    while(y > 0) {
        if(y & 1)res = res * x % Pt;
        y >>= 1;
        x = x * x % Pt;
    }
    return res;
}
bool cmp(NOOD a, NOOD b) {
    if(B[a.l] == B[b.l])return a.r < b.r;
    else return a.l < b.l;
}
void Init() {
    P[0] = 1; rP[0] = qwe(P[0], Pt - 2);
    for(int i = 1; i <= maxn; i++) {
        P[i] = P[i - 1] * i % Pt;
        rP[i] = qwe(P[i], Pt - 2);
    }
    int unit = sqrt(maxn);
    for(int i = 1; i <= maxn; i++)B[i] = i / unit + 1;
    scanf("%d", &T);
    for(int i = 1; i <= T; i++)scanf("%d%d", &q[i].r, &q[i].l), q[i].id = i;
    sort(q + 1, q + T + 1, cmp);
}
LL C(int n, int m) {
    return P[n] * rP[n - m] % Pt * rP[m] % Pt;
}
vector<pair<int, LL> > ans;
int main() {
    LL res = 0;
    Init();
    int l = q[1].l, r = q[1].r;
    for(int i = 0; i <= l; i++)res = (res + C(r, i)) % Pt;
    ans.push_back(make_pair(q[1].id, res));
    for(int i = 2; i <= T; i++) {
        while(r < q[i].r) {
            res = ((res * 2 - C(r, l)) % Pt + Pt) % Pt;
            r++;
        }
        while(r > q[i].r) {
            r--;
            res = (res + C(r, l)) % Pt * rP[2] % Pt;
        }
        while(l < q[i].l) {
            l++;
            res = (res + C(r, l)) % Pt;
        }
        while(l > q[i].l) {
            res = ((res - C(r, l)) % Pt + Pt) % Pt;
            l--;
        }
        ans.push_back(make_pair(q[i].id, res));
    }
    sort(ans.begin(), ans.end());
    for(int i = 0; i < ans.size(); i++)printf("%lld\n", ans[i].second);
    return 0;
}
posted @ 2018-08-02 15:36  呵呵!!!  阅读(97)  评论(0编辑  收藏  举报