【bzoj4542】[Hnoi2016]大数 莫队
| 
 Description  小 B 有一个很大的数 S,长度达到了 N 位;这个数可以看成是一个串,它可能有前导 0,例如00009312345  Input  第一行一个整数:P。第二行一个串:S。第三行一个整数:M。接下来M行,每行两个整数 fr,to,表示对S 的  Output输出M行,每行一个整数,第 i行是第 i个询问的答案。 Sample Input11 121121 3 1 6 1 5 1 4 Sample Output5 3 2 //第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。 HINT2016.4.19新加数据一组 Source感觉可以离线? 用a[i]表示前i个数连起来的数,则题目让求: 把 
    然后关于p=2或5需要特判,因为这时候 
    #include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
typedef long long LL;
const int SZ = 1000010;
const int INF = 1000000010;
int B,len,t[SZ],cnt = 0,n;
map<LL,int> mp;
LL s[SZ],p;
char str[SZ];
struct haha{
    int l,r,id;
    LL ans;
}ask[SZ];
bool cmp1(haha a,haha b)
{
    if(a.l / B == b.l / B) return a.r < b.r;
    return a.l < b.l;
}
bool cmp2(haha a,haha b)
{
    return a.id < b.id;
}
int id[SZ];
LL get(LL x)
{
    return x * (x - 1);
}
namespace work25{
    int t[SZ],sum[SZ];
    void solve()
    {
        for(int i = 1;i <= n;i ++)
        {
            if((str[i] - '0') % p == 0)
                t[i] = t[i - 1] + 1,sum[i] = sum[i - 1] + i;
            else
                t[i] = t[i - 1],sum[i] = sum[i - 1];
        }
        int m;
        scanf("%d",&m);
        for(int i = 1;i <= m;i ++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%lldn",(sum[r] - sum[l - 1]) - ((LL)t[r] - t[l - 1]) * (l - 1));
        }
    }
}
int main()
{
    scanf("%lld",&p);
    scanf("%s",str + 1);
    n = strlen(str + 1);
    if(p == 2 || p == 5)
    {
        work25 :: solve();
        return 0;
    }
    B = sqrt(n);
    for(int i = n;i >= 1;i --)
    {
        static LL x = 1;
        x = x * 10 % p;
        s[i] = (s[i + 1] + x * (str[i] - '0') % p) % p;
        if(!mp[s[i]]) mp[s[i]] = ++ cnt;
    }
    for(int i = 1;i <= n + 1;i ++)
        id[i] = mp[s[i]];
    int m;
    scanf("%d",&m);
    for(int i = 1;i <= m;i ++)
    {
        scanf("%d%d",&ask[i].l,&ask[i].r); ask[i].r ++;
        ask[i].id = i;
    }
    sort(ask + 1,ask + 1 + m,cmp1);
    LL ans = 0;
    for(int i = 1,l = 1,r = 0;i <= m;i ++)
    {
        for(;r > ask[i].r;r --) { ans -= get(t[id[r]]); t[id[r]] --; ans += get(t[id[r]]); }
        for(;r < ask[i].r;r ++) { ans -= get(t[id[r + 1]]); t[id[r + 1]] ++; ans += get(t[id[r + 1]]); }
        for(;l > ask[i].l;l --) { ans -= get(t[id[l - 1]]); t[id[l - 1]] ++; ans += get(t[id[l - 1]]); }
        for(;l < ask[i].l;l ++) { ans -= get(t[id[l]]); t[id[l]] --; ans += get(t[id[l]]); }        
        ask[i].ans = ans >> 1;
    }
    sort(ask + 1,cmp2);
    for(int i = 1;i <= m;i ++)
        printf("%lldn",ask[i].ans);
    return 0;
}(编辑:91站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! | 


