题目大意
解题思路
可以发现当p较小时可以预处理出%p后的前缀和,把询问挂在每个点分别处理。当p较大时可以开一个桶,枚举合法的原数统计答案不会很多。
code
using namespace std;
int const maxn=100000,mida=100,maxa=10000,inf=2147483647;
int n,m,gra1,gra2,a[maxn+10],cnt[mida+2][maxn+2],h[mida+2][maxn+2],pos1[maxn*65+10],val1[maxn*65+10],next1[maxn*65+10],pos2[maxn*65+10],val2[maxn*65+10],mo[maxn*65+10],next2[maxn*65+10],begin1[maxn+10],begin2[maxn+10],ans[maxn+10],mod=1000000007;
void insert1(int u,int v,int p){
pos1[++gra1]=p;
val1[gra1]=v;
next1[gra1]=begin1[u];
begin1[u]=gra1;
}
void insert2(int u,int m,int v,int p){
pos2[++gra2]=p;
val2[gra2]=v;
mo[gra2]=m;
next2[gra2]=begin2[u];
begin2[u]=gra2;
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,n)
scanf("%d",&a[i]);
fo(i,1,m){
int l,r,p,q;scanf("%d%d%d%d",&l,&r,&p,&q);
if(p>mida){
for(int j=q;j<=maxa;j+=p)
insert1(l-1,j,-i),insert1(r,j,i);
}
else{
insert2(l-1,p,q,-i),insert2(r,p,q,i);
}
}
fo(i,1,n){
int p=a[i];
h[mida+1][p]=a[i];cnt[mida+1][p]++;
fo(j,1,mida){
int p=a[i]%j;
h[j][p]=a[i]%j;cnt[j][p]++;
}
for(int j=begin1[i];j;j=next1[j])
ans[abs(pos1[j])]+=cnt[mida+1][val1[j]]*((pos1[j]>0)?1:-1);
for(int j=begin2[i];j;j=next2[j])
ans[abs(pos2[j])]+=cnt[mo[j]][val2[j]]*((pos2[j]>0)?1:-1);
}
fo(i,1,m)printf("%d\n",ans[i]);
return 0;
}