bzoj5452[Hnoi2016]大数(莫队)

Posted quzhizhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5452[Hnoi2016]大数(莫队)相关的知识,希望对你有一定的参考价值。

  题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4542

  首先若p=2,5则这题就是道傻逼题,前缀和搞一下没了。如果p为其他质数,那么可以这么处理:

  我们先预处理出数组num[i]表示原串第i~n位表示的数模p的余数,那么第l~r位表示的数模p的余数为(num[l]-num[r+1])/10^(n-r),因为10^(n-r)与p互质,所以若num[l]=num[r+1],则第l~r位表示的数是p的倍数。于是莫队一下就好了。

  代码:

技术分享图片
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<string>
#include<iostream> 
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 2000010
inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<0||9<c;c=getchar())if(c==-)f=-1; for(;0<=c&&c<=9;c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-0; return tmp*f;}
inline ll power(ll a,ll b){ll ans=1; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
using namespace std;
struct data{
    int l,r,id;
}a[100010];
struct data2{
    ll val;
    int id;
}x[100010];
char s[100010];
ll rk[100010],cnt[100010],ans[100010],sum1[100010],sum2[100010];
int n,m,size;
ll p,tot;
bool cmp(data a,data b){return a.l/size!=b.l/size?a.l/size<b.l/size:a.r<b.r;}
bool cmp2(data2 a,data2 b){return a.val<b.val;}
int main()
{
    p=read();
    scanf("%s",s); n=strlen(s); size=sqrt(n);
    m=read();
    if(p==2||p==5){
        sum1[0]=sum2[0]=0;
        for(int i=1;i<=n;i++){
            sum1[i]=sum1[i-1]; sum2[i]=sum2[i-1];
            if((s[i-1]-0)%p==0)++sum1[i],sum2[i]+=i;
        }
        for(int i=1;i<=m;i++){
            int l=read(),r=read();
            printf("%lld
",sum2[r]-sum2[l-1]-(sum1[r]-sum1[l-1])*(l-1));
        }
        fclose(stdin); fclose(stdout);
        return 0;
    }
    for(int i=1;i<=m;i++)
        a[i].l=read()-1,a[i].r=read(),a[i].id=i;
    sort(a+1,a+m+1,cmp);
    ll tmp=1; x[n].val=0; x[n].id=n;
    for(int i=n-1;i>=0;i--,tmp=tmp*10%p)x[i].val=(x[i+1].val+(s[i]-0)*tmp)%p,x[i].id=i;
    sort(x,x+n+1,cmp2);
    rk[x[0].id]=0;
    for(int i=1;i<=n;i++)
        if(x[i].val==x[i-1].val)rk[x[i].id]=rk[x[i-1].id];
        else rk[x[i].id]=i;
    tot=0;
    for(int i=a[1].l;i<=a[1].r;i++)
        tot+=cnt[rk[i]]++;
    ans[a[1].id]=tot;
    for(int i=2;i<=m;i++){
        if(a[i-1].l<a[i].l){
            for(int j=a[i-1].l;j<a[i].l;j++)
                tot-=--cnt[rk[j]];
        }
        else{
            for(int j=a[i].l;j<a[i-1].l;j++)
                tot+=cnt[rk[j]]++;
        }
        if(a[i-1].r<a[i].r){
            for(int j=a[i-1].r+1;j<=a[i].r;j++)
                tot+=cnt[rk[j]]++;
        }
        else{
            for(int j=a[i].r+1;j<=a[i-1].r;j++)
                tot-=--cnt[rk[j]];
        }
        ans[a[i].id]=tot;
    }
    for(int i=1;i<=m;i++)
        printf("%lld
",ans[i]);
}
bzoj4542

 

以上是关于bzoj5452[Hnoi2016]大数(莫队)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4542[Hnoi2016]大数 莫队

[BZOJ4542][HNOI2016]大数(莫队)

莫队bzoj4542: [Hnoi2016]大数

bzoj4542: [Hnoi2016]大数(莫队)

bzoj4542[Hnoi2016]大数 莫队算法

[BZOJ4542] [JZYZOJ2014][Hnoi2016] 大数(莫队+离散化)