题解:CF1921F Sum of Progression
根号分治模板题。
对于这种题目,直接暴力显然是不行的。于是要用到根号分治。
根号分治的基本思路就是设一个阈值
-
d \ge B
这种情况下直接暴力。
if (d>=B){
int ans=0;
for (int now=s,i=1;i<=k;now+=d,i++){
ans+=a[now]*i;
}
cout<<ans<<' ';
}
-
d < B
这种情况下需要预处理。我们设
(中括号不是艾弗森括号,只是普通的中括号)。
然后:
for (int i=1;i<B;i++){
for (int j=1;j<=n;j++){
if (j<=i) sum[i][j]=a[j],sum2[i][j]=a[j];
else sum[i][j]=sum[i][j-i]+(j+i-1)/i*a[j],sum2[i][j]=sum2[i][j-i]+a[j];
}
}
于是有:
(式子稍微有点长,具体可以看代码)。
else{
int L=s,R=s+(k-1)*d;
int ans1=sum[d][R]-sum[d][L-d];
int cnt=(s+d-1)/d-1;
int ans2=cnt*(sum2[d][R]-sum2[d][L-d]);
cout<<ans1-ans2<<' ';
}
那么时间复杂度为
完整代码