分析
在我看了二十分钟题后,才发现被模的数是下标,不是值(美好),然后就开始换做法。
对于每一个模数 \(x\) ,我们发现第一个符合要求的就是 \(y\) ,之后每一个符合要求的数就是前一个数加上 \(x\) ,这样的话每一次的操作时间复杂度就是 \(n/x\),这样我们发现如果每一个 \(x\) 都很小的话,时间复杂度就达到了 \(n^2\),所以我们如何优化呢?
由前面可知我们所忌惮的就是小的 \(x\),因此我们可以设置一个较小的数,存储比它小的数作为模数时各结果的答案,然后当 \(x\) 小于这个限度时,就可以直接输出了,对于每一个修改的数,计算限定数次数,对于所给 \(x\) 大于该限定数的,计算 \(n/x\) 次,因此我们可以得到当限定数 \(t\) 设为 \(\sqrt{n}\) 时,极限的时间复杂度即为 \((m+n)\sqrt{n}\),至此此题得解。
代码
#include<bits/stdc++.h>
using namespace std;
int a[150001],x,y,ans[400][400],rt,n,m;
char op[10];
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
while(c>=‘0‘&&c<=‘9‘){res=(res<<1)+(res<<3)+c-48;c=getchar();}
res*=f;
}
int main()
{
read(n);
read(m);
rt=sqrt(n);//限度
for(int i=1;i<=n;++i){
read(a[i]);
for(int j=1;j<=rt;j++)ans[j][i%j]+=a[i];//存储限度内的答案
}
for(int i=1;i<=m;++i){
scanf("%s",op);read(x);read(y);
if(op[0]==‘A‘){
if(x<=rt)printf("%d\n",ans[x][y]);
else{//题目中说了输入合法,否则我觉得还是判断x与y的大小为好
int s=0;
for(int j=y;j<=n;j+=x){//分析中的计算方法
s+=a[j];
}
printf("%d\n",s);
}
}
if(op[0]==‘C‘){
for(int j=1;j<=rt;j++)ans[j][x%j]+=(y-a[x]);//将存储答案更新
a[x]=y;
}
}
return 0;
}