分析

在我看了二十分钟题后,才发现被模的数是下标,不是值(美好),然后就开始换做法。

对于每一个模数 \(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;
}
posted on 2021-08-28 21:17  漠寒·  阅读(41)  评论(0编辑  收藏  举报