HDU_1175_莫队+逆元

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

初探莫队,就是离线排序后的暴力,但是效率大大提高,中间要除法取模,所以用到了逆元。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
#define MOD 1000000007 
using namespace std;

int a[30005],num[30005],n,m,sizee;
LL ans[30005],inv[30005];
struct node
{
    int l,r,num,belong;
}query[30005];

void init()
{
    for(int i = 1;i <= 30000;i++)
    {
        LL temp = 1,x = i;
        int pow = MOD-2;
        while(pow)
        {
            if(pow%2)    temp = temp*x%MOD;
            x = x*x%MOD;
            pow /= 2;
        }
        inv[i] = temp;
    }
}

int cmp(node x,node y)
{
    if(x.belong == y.belong)    return x.r < y.r;
    return x.l<y.l;
}

int main()
{
    init();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        sizee = sqrt(n);
        for(int i = 1;i <= n;i++)    scanf("%d",&a[i]);
        for(int i = 1;i <= m;i++)
        {
            scanf("%d%d",&query[i].l,&query[i].r);
            query[i].num = i;
            query[i].belong = (query[i].l-1)/sizee+1;
        }
        sort(query+1,query+1+m,cmp);
        memset(num,0,sizeof(num));
        int ll = 1,rr = 1;
        LL now = 1;
        num[a[1]]++;
        for(int i = 1;i <= m;i++)
        {
            while(rr < query[i].r)
            {
                rr++;
                num[a[rr]]++;
                now = now*(rr-ll+1)%MOD*inv[num[a[rr]]]%MOD;
            }
            while(ll > query[i].l)
            {
                ll--;
                num[a[ll]]++;
                now = now*(rr-ll+1)%MOD*inv[num[a[ll]]]%MOD;
            }
            while(ll < query[i].l)
            {
                now = now*num[a[ll]]%MOD*inv[rr-ll+1]%MOD;
                num[a[ll]]--;
                ll++;
            }
            while(rr > query[i].r)
            {
                now = now*num[a[rr]]%MOD*inv[rr-ll+1]%MOD;
                num[a[rr]]--;
                rr--;
            }
            ans[query[i].num] = now;
        }
        for(int i = 1;i <= m;i++)    printf("%lld
",ans[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhurb/p/5934349.html