小 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的倍数。
小 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的倍数。
第一行一个整数:P。
第二行一个串:S。
第三行一个整数:M。
接下来M行,每行两个整数 fr,to,表示对S 的子串S[fr…to]的一次询问。
注意:S的最左端的数字的位置序号为 1;例如S为213567,则S[1]为 2,S[1…3]为 213。
N,M<=100000,P为素数
输出M行,每行一个整数,第 i行是第 i个询问的答案。
2016.4.19新加数据一组
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<map>
#include<cmath>
#include<cstring>
#define MAXN 100010
using namespace std;
map<long long,long long> ranks;
int n,m;
long long p,val[MAXN];
long long front[MAXN],ans[MAXN],sum[MAXN],b[MAXN],num[MAXN];
struct node{
int l,r,id;
}que[MAXN];
inline long long read(){
long long date=0,w=1;char c=0;
while(c<‘0‘||c>‘9‘){if(c==‘-‘)w=-1;c=getchar();}
while(c>=‘0‘&&c<=‘9‘){date=date*10+c-‘0‘;c=getchar();}
return date*w;
}
bool cmp1(const node &x,const node &y){
return x.l<y.l;
}
bool cmp2(const node &x,const node &y){
if(x.r==y.r)return x.l<y.l;
return x.r<y.r;
}
void work1(){
for(int i=1;i<=n;i++){
front[i]=front[i-1];sum[i]=sum[i-1];
if(val[i]%p==0){
front[i]+=i;
sum[i]++;
}
}
while(m--){
int l=read(),r=read();
printf("%lld\n",front[r]-front[l-1]-(sum[r]-sum[l-1])*(l-1));
}
}
void work2(){
int nowi=1,nowj=0,x,d,left=1,right=0;
long long s;
for(int i=1;i<=m;i++){
que[i].l=read();que[i].r=read();
que[i].id=i;
}
x=sqrt(n);
sort(que+1,que+m+1,cmp1);
while(nowi<=m){
nowj++;
d=nowi;
while(que[nowi].l<nowj*x&&nowi<=m)nowi++;
sort(que+d,que+nowi,cmp2);
if(nowj==x){
sort(que+d,que+m+1,cmp2);
break;
}
}
s=1;
for(int i=n;i>=1;i--,s=s*10%p)b[i]=sum[i]=(val[i]*s%p+sum[i+1])%p;
sort(b+1,b+n+2);
for(int i=1;i<=n+1;i++)ranks[b[i]]=i;
for(int i=1;i<=n+1;i++)sum[i]=ranks[sum[i]];
s=0;
for(int i=1;i<=m;i++){
while(que[i].l<left)
{
left--;
s+=num[sum[left]];
num[sum[left]]++;
}
while(que[i].l>left)
{
s-=num[sum[left]]-1;
num[sum[left]]--;
left++;
}
while(right<que[i].r+1)
{
right++;
s+=num[sum[right]];
num[sum[right]]++;
}
while(right>que[i].r+1)
{
s-=num[sum[right]]-1;
num[sum[right]]--;
right--;
}
ans[que[i].id]=s;
}
for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
}
void init(){
char ch[MAXN];
p=read();scanf("%s",ch);m=read();
n=strlen(ch);
for(int i=0;i<n;i++)val[i+1]=ch[i]-‘0‘;
}
int main(){
init();
if(p==2||p==5)work1();
else work2();
return 0;
}
原文:https://www.cnblogs.com/Yangrui-Blog/p/9460409.html