bzoj2506 calc
题解:
首先,将询问$(l,r)$改为$(1,r)-(1,l-1)$。
由于$p<=10000$,可以考虑对$p$分治。
若$p<=100$,我们可以存模$p$等于$k$的有多少个,次数为$100*k,k<=n$;
若$100<=p<=10000$,可以暴力枚举有哪几个数模$p$等于$k$,枚举不超过$100$次,时间复杂度最多$k*m,k<=100$。
然后就能过了……
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,m,w[N],ans[N],tot; struct node { int p,k,i,d,t; node(){} node(int p,int k,int i,int d,int t):p(p),k(k),i(i),d(d),t(t){} }q[N<<1]; bool cmp(node a,node b){return a.d<b.d;} int h1[105][105],h2[N]; int cot(int p,int k) { if(p<=100)return h1[p][k]; int ret = 0; for(;k<=10000;k+=p) ret += h2[k]; return ret; } int main() { // freopen("tt.in","r",stdin); read(n),read(m); for(int i=1;i<=n;i++) read(w[i]); for(int l,r,P,k,i=1;i<=m;i++) { read(l),read(r),read(P),read(k); if(l>1)q[++tot]=node(P,k,i,l-1,-1); q[++tot]=node(P,k,i,r,1); } sort(q+1,q+1+tot,cmp); for(int I=1,i=1;i<=n;i++) { h2[w[i]]++; for(int j=1;j<=100;j++) h1[j][w[i]%j]++; while(q[I].d==i) { ans[q[I].i]+=q[I].t*cot(q[I].p,q[I].k); I++; } } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }