【魔改】莫队算法+组合数公式 杭电多校赛4 Problem B. Harvest of Apples

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

莫队算法是一个离线区间分块瞎搞算法,只要满足:1.离线  2.可以O(1)从区间(L,R)更新到(L±1,R±1)就能直接套板子了

这道题不是区间算法,但是有递推式:

把它看成区间更新orz

所以可以莫队orz

#define _CRT_SECURE_NO_WARNINGS
#include    <cmath>
#include <iostream>
#include    <stdio.h>
#include<algorithm>
#include        <map>
#include     <cstring>
#include      <time.h>
using namespace std;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5 + 5;
const long long mod = 1e9 + 7;
map<int, int> mmp;
typedef long long ll;
struct node {
    int l, r, id;

}Q[maxn];
ll fac[maxn], infac[maxn];
long long ans[maxn];
long long num[maxn];
int a[maxn], pos[maxn];
int n, m, k;
int L = 1, R = 0;
long long Ans = 0;

ll cal(ll x) {
    ll res = 1;
    int k = mod - 2;
    while (k) {
        if (k & 1) {
            res *= x;
            res %= mod;
        }
        x *= x;
        x %= mod;
        k >>= 1;
    }
    return res;//cal(x^ mod)
}
void init() {
    fac[0] = 1;
    rep(i, 1, maxn - 1)fac[i] = (fac[i-1] * i)%mod;
    rep(i, 0, maxn - 1)infac[i] = cal(fac[i]);
}
ll C(ll a, ll b)
{
    return 1ll * fac[a] * infac[b] % mod * infac[a - b] % mod;
}
bool cmp(node a, node b) {
    if (pos[a.r] == pos[b.r])
        return a.l < b.l;
    return pos[a.r] < pos[b.r];

}
void add(int x) {

    //num[a[x]]++;
    //if (num[a[x] - 1] == 0 && num[a[x] + 1] == 0)Ans++;
    //else if (num[a[x] - 1] && num[a[x] + 1])Ans--;
    Ans += C(n, m);

}
void addl(int x) {

}
void del(int x) {
    //num[a[x]]--;
    //if (num[a[x] - 1] == 0 && num[a[x] + 1] == 0)Ans--;
    //else if (num[a[x] - 1] && num[a[x] + 1])Ans++;
    Ans -= C(n, m + 1);
}

int smain() {
    int t; scanf("%d", &t);
    init();
        Ans = 0;
        mmm(num, 0);
        L = 1, R = 0;
        
        int sz = sqrt(1e5);
        for (int i = 1; i <= 1e5; i++) {
            pos[i] = i / sz;
        }

        rep(i,1,t) {
            scanf("%d%d", &Q[i].l, &Q[i].r);
            Q[i].id = i;
        }
        sort(Q + 1, Q + 1 + t, cmp);
        Ans = 0;//S(m,n
        L = Q[1].l; R = -1;
        rep(i,1,t){
            while (L < Q[i].l) {
                //del(L);
                Ans = (2ll * Ans - C(L, R) + mod) % mod;
                ++L;
            }

            while (L > Q[i].l) {
                --L;
                //addl(L);
                Ans = ((Ans + C(L, R)) *infac[2]%mod) % mod;
            }


            while (R < Q[i].r) {
                ++R;
                //add(R);
                Ans = (Ans+C(L, R))%mod;
            }
            while (R > Q[i].r) {
                //del(R);
                Ans = (Ans-C(L, R)+mod)%mod;
                --R;

            }
            
            ans[Q[i].id] = Ans;
        }
        rep(i,1,t)printf("%lld
", ans[i]);
    return 0;
}
/*


6
60522 25373
36426 3283
48772 42553
33447 12441
3497 2182
7775 4025

*/
#define ONLINE_JUDGE
int main() {
    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    cin >> n;
    return 0;
}
成功的路并不拥挤,因为大部分人都在颓(笑)
原文地址:https://www.cnblogs.com/SuuT/p/9418157.html