zoukankan      html  css  js  c++  java
  • BZOJ4542: [Hnoi2016]大数

    Description

      小 B 有一个很大的数 S,长度达到了 N 位;这个数可以看成是一个串,它可能有前导 0,例如00009312345
    。小B还有一个素数P。现在,小 B 提出了 M 个询问,每个询问求 S 的一个子串中有多少子串是 P 的倍数(0 也
    是P 的倍数)。例如 S为0077时,其子串 007有6个子串:0,0,7,00,07,007;显然0077的子串007有6个子串都是素
    数7的倍数。

    Input

      第一行一个整数:P。第二行一个串:S。第三行一个整数:M。接下来M行,每行两个整数 fr,to,表示对S 的
    子串S[fr…to]的一次询问。注意:S的最左端的数字的位置序号为 1;例如S为213567,则S[1]为 2,S[1…3]为 2
    13。N,M<=100000,P为素数

    Output

      输出M行,每行一个整数,第 i行是第 i个询问的答案。

    Sample Input

    11
    121121
    3
    1 6
    1 5
    1 4

    Sample Output

    5
    3
    2
    //第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。

    HINT

     2016.4.19新加数据一组

     
    一场考试中两道莫队,出题人什么心态。。。
    预处理后缀倒序的结果S,那么一个区间[l,r]的数就是(S[l]-S[r+1])/(10^(r-l+1))。
    注意p是一个质数,所以当p!=2且p!=5时10^k肯定与p互质,这样只用比较S[l]和S[r+1]是否大小相等,即转化成经典的莫队问题。
    当p=2或p=5时一个数是否合法只与末尾有关,类似莫队一下即可。
    #include<cstdio>
    #include<cctype>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    typedef long long ll;
    inline ll read() {
        ll x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int n,m,type,blo[maxn];
    char s[maxn];
    ll p,ans[maxn],tmp[maxn],A[maxn],nowans;
    struct Query {
    	int l,r,id;
    	bool operator < (const Query& ths) const {
    		if(blo[l]!=blo[ths.l]) return l<ths.l;
    		return r<ths.r;
    	}
    }Q[maxn];
    int c[maxn],l=1,r,k;
    void Add(int x) {nowans+=c[x];c[x]++;}
    void Del(int x) {c[x]--;nowans-=c[x];}
    void Addl(int x) {if(x%p==0) k++;nowans+=k;}
    void Addr(int x) {if(x%p==0) k++,nowans+=(r-l+1);}
    void Dell(int x) {nowans-=k;if(x%p==0) k--;}
    void Delr(int x) {if(x%p==0) k--,nowans-=(r-l+2);}
    void solve() {
    	sort(Q+1,Q+m+1);
    	if(type) {
    		ll t=1;
    		dwn(i,n,1) {
    			A[i]=(A[i+1]+t*(s[i]-'0'))%p;
    			(t*=10)%=p;
    		}
    		rep(i,1,n+1) tmp[i]=A[i];
    		sort(tmp+1,tmp+n+2);
    		rep(i,1,n+1) A[i]=lower_bound(tmp+1,tmp+n+2,A[i])-tmp;
    		rep(i,1,m) {
    			while(l>Q[i].l) Add(A[--l]);
    			while(r<Q[i].r) Add(A[++r]);
    			while(l<Q[i].l) Del(A[l++]);
    			while(r>Q[i].r) Del(A[r--]);
    			ans[Q[i].id]=nowans;
    		}
    	}
    	else rep(i,1,m) {
    		while(l>Q[i].l) Addl(s[--l]-'0');
    		while(r<Q[i].r) Addr(s[++r]-'0');
    		while(l<Q[i].l) Dell(s[l++]-'0');
    		while(r>Q[i].r) Delr(s[r--]-'0');
    		ans[Q[i].id]=nowans;
    	}
    	rep(i,1,m) printf("%lld
    ",ans[i]);
    }
    int main() {
    	p=read();scanf("%s",s+1);n=strlen(s+1);
    	m=read();int SIZE=(int)sqrt(n);
    	rep(i,1,n) blo[i]=(i-1)/SIZE+1;
    	if(p!=2&&p!=5) type=1;
    	if(type) rep(i,1,m) Q[Q[i].id=i].l=read(),Q[i].r=read()+1;
    	else rep(i,1,m) Q[Q[i].id=i].l=read(),Q[i].r=read();
    	solve();
    	return 0;
    }
    

      

  • 相关阅读:
    java 基础知识
    winform判断一个事件是否已经绑定了事件处理函数
    优质文章
    优质博客
    缩略图的创建
    记录一次错误处理 (xml序列化和反序列化相关)
    文件同步软件
    博客园优质博主集锦
    不错的博文集锦
    cesiumjs
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5418412.html
Copyright © 2011-2022 走看看