题意:n个数a[i],m次询问n,m<=3e5,a[i]<=1e9.每次询问给出(x,y) 问a[x]+a[x+y]+a[x+2y]..+a[x+ky] (x+ky<=n)
直接模拟显然是TLE,由于当y很大时,例如y>=sqrt(n) 模拟一次最坏为O(sqrt(n)) 所以y>=sqrt(n) 直接暴力,这部分为O(nsqrt(n))当y<sqrt(n)=550,显然可以预处理出部分和d[i] 表示以i开头的 步长为y的部分和,d[i]=d[i+y]+a[i];总共sqrt(n)组 每组O(n) 这部分也为O(nsqrt(n))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=3e5+20;
const int M=650;
ll a[N],n,m;
ll d[N],res[N];
struct node{
int x,y,id;
}p[N];
bool cmp(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
bool cmp_id(node a,node b)
{
return a.id<b.id;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
int b=sqrt(n);
cin>>m;
for(int i=0;i<m;i++)
scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i;
sort(p,p+m,cmp);
for(int i=0;i<m;i++)
{
ll ans=0;
if(p[i].y>=b)
{
int x=p[i].x;
while(x<=n)
{
ans+=a[x];
x+=p[i].y;
}
}
else
{
if(i==0||(i-1>=0&&p[i].y!=p[i-1].y))//对相同的y进行预处理 sqrt(n)组 每组O(n)
{
memset(d,0,sizeof(d));
for(int k=n;k>=1;k--)
{
d[k]=a[k];
if(k+p[i].y<=n)
d[k]+=d[k+p[i].y];
}
}
ans=d[p[i].x];
}
res[p[i].id]=ans;
}
sort(p,p+m,cmp_id);
for(int i=0;i<m;i++)
printf("%I64d\n",res[i]);
}
return 0;
}