BZOJ 4542([Hnoi2016]序列-莫队)

来源:互联网 发布:浙江广信数据有限公司 编辑:程序博客网 时间:2024/06/04 19:49

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新加数据一组

如果gcd(p,10)=1,显然一个子串是k的倍数当且仅当它的2个后缀mod p余数相同。
当p是2,5的时候可以根据最后一位判断。
这2种情况都可以用莫队。

#include<bits/stdc++.h> using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define ForkD(i,k,n) for(int i=n;i>=k;i--)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (o<<1)#define Rson ((o<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,0x3f,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define MEMx(a,b) memset(a,b,sizeof(a));#define INF (0x3f3f3f3f)#define F (1000000007)#define pb push_back#define mp make_pair#define fi first#define se second#define vi vector<int> #define pi pair<int,int>#define SI(a) ((a).size())#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;#define PRi2D(a,n,m) For(i,n) { \                        For(j,m-1) cout<<a[i][j]<<' ';\                        cout<<a[i][m]<<endl; \                        } #pragma comment(linker, "/STACK:102400000,102400000")#define ALL(x) (x).begin(),(x).end()typedef long long ll;typedef long double ld;typedef unsigned long long ull;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return ((a-b)%F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}inline int read(){    int x=0,f=1; char ch=getchar();    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}    return x*f;} #define MAXN (100010)ll b[MAXN],res[MAXN],belong[MAXN],cnt[MAXN]={};struct node{    int l,r,id;    friend bool operator<(node a,node b) {        if (belong[a.l] ^ belong[b.l] )            return belong[a.l] < belong[b.l];        return a.r<b.r;     }}a[MAXN];char s[MAXN];ll c[MAXN];map<ll,int> h;int main(){//  freopen("bzoj4542.in","r",stdin);//  freopen(".out","w",stdout);    ll p;cin>>p;    scanf("%s",s+1);    int n=strlen(s+1);    int m=read();    int BS=sqrt(n);    For(i,m){        a[i]=node{read(),read(),i};    }    For(i,n)        belong[i]=(i-1)/BS+1;    int l=1,r=0;    if (p==2||p==5) {        sort(a+1,a+m+1);        ll t=0,ans=0;        For(i,m){            while(l>a[i].l){                l--,t+=((s[l]-'0')%p)==0,ans+=t;            }while(r<a[i].r){                r++;                if (((s[r]-'0')%p)==0) {                    t++;                    ans+=r-l+1;                 }            }while(l<a[i].l){                if (((s[l]-'0')%p)==0) {                    ans-=t; t--;                } else {                    ans-=t;                }                l++;            }while(r>a[i].r){                if (((s[r]-'0')%p)==0) {                    ans-=r-l+1;                     t--;                }                r--;            }            res[a[i].id]=ans;        }    }    else {        ll t=0,c10=1;        ForD(i,n) {            t=(t+c10*(s[i]-'0'))%p;            c[i]=t;            c10=(c10*10)%p;        }        c[n+1]=0;        For(i,n+1) h[c[i]]=1;        int pid=0;        for(map<ll,int>::iterator it=h.begin();it!=h.end();it++) {            it->se=++pid;//          cout<<it->se<<endl;        }//      For(i,n) cout<<c[i]<<' '<<h[c[i]]<<endl;        For(i,n+1) c[i]=h[c[i]];        For(i,n) a[i].r++;        sort(a+1,a+m+1);        ll ans=0;        MEM(cnt)        For(i,m){            while(l>a[i].l){                --l;                ans+=cnt[c[l]]++;            }while(r<a[i].r){                ++r;                ans+=cnt[c[r]]++;            }while(l<a[i].l){                ans-=--cnt[c[l]];                l++;            }while(r>a[i].r){                ans-=--cnt[c[r]];                r--;            }            res[a[i].id]=ans;        }    }    For(i,m)        printf("%lld\n",res[i]);    return 0;}
0 0
原创粉丝点击