思路:考虑离线操作,以y为关键字排序,对于y相同的一起操作,然后考虑y的范围,当y<=sqrt(n)时,直接O(n)预处理出f[x]表示f[x]+f[x+y]+f[x+2*y]+..+f[x+k*y]的答案,然后这样的y显然不超过sqrt(n)个,复杂度也就是O(n*sqrt(n))的;如果y>sqrt(n),那么这样直接暴力统计答案,因为答案的项数也显然不会超过sqrt(n),这样整个算法的时间复杂度就是O(n*sqrt(n))。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 #define maxn 300005 8 9 int n,Q; 10 int a[maxn]; 11 long long f[maxn],ans[maxn]; 12 13 struct query{ 14 int x,y,id; 15 bool operator <(const query &a)const{return y<a.y;} 16 }q[maxn]; 17 18 int read(){ 19 int x=0;char ch=getchar(); 20 for (;ch<'0'||ch>'9';ch=getchar()); 21 for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 22 return x; 23 } 24 25 int main(){ 26 n=read();int size=sqrt(n); 27 for (int i=1;i<=n;i++) a[i]=read(); 28 Q=read(); 29 for (int i=1;i<=Q;i++) q[i].x=read(),q[i].y=read(),q[i].id=i; 30 sort(q+1,q+Q+1); 31 for (int i=1;i<=Q;i++){ 32 if (q[i].y<=size){ 33 int y=q[i].y; 34 if (y!=q[i-1].y) for (int j=n;j;j--) f[j]=(j+y>n?a[j]:f[j+y]+a[j]); 35 ans[q[i].id]=f[q[i].x]; 36 } 37 else{ 38 int x=q[i].x,y=q[i].y,id=q[i].id; 39 while (x<=n) ans[id]+=a[x],x+=y; 40 } 41 } 42 for (int i=1;i<=Q;i++) printf("%I64d ",ans[i]); 43 return 0; 44 }