题目描述
众所周知,模数的hash会产生冲突。例如,如果模的数p=7,那么4和11便冲突了。
B君对hash冲突很感兴趣。他会给出一个正整数序列value[]。
自然,B君会把这些数据存进hash池。第value[k]会被存进(k%p)这个池。这样就能造成很多冲突。
B君会给定许多个p和x,询问在模p时,x这个池内数的总和。
另外,B君会随时更改value[k]。每次更改立即生效。
保证
1 <= p < n , 1 <= p < n
1 <= p < n.
数据规模
对于10%的数据,有n<=1000,m<=1000.
对于60%的数据,有n<=100000.m<=100000.
对于100%的数据,有n<=150000,m<=150000.
保证所有数据合法,且1<=value[i]<=1000.
解法:每次询问的答案为:
for(int i = y; i <= n; i += x) ans += value[i]
观察到当x较大时,复杂度较低,x较小时复杂度较高
考虑预处理答案:ans[p][k] 表示 所有位置% p 余 k 的位置的数的和。枚举复杂度为o(n ^ 2)
考虑block 取 sqrt(n) 时,可以用n * sqrt(n)的时间预处理出 x <= sqrt(n)的所有可能答案。
对于x <= block的询问,直接o(1) 输出预处理的答案。
对于x > block的询问,因为此时x > sqrt(n),可以在sqrt(n)时间内得到答案。
考虑更新,修改一个值后,暴力枚举 p, 更新ans[p][x % p]的值,复杂度也为sqrt(n)。
总复杂度为o((n + m) * sqrt(n));
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
const int mx = 2e3 + 10;
int num,block,n,m,q,l[1100],r[1100],belong[maxn];
int a[maxn],ans[maxn][1100];
char op[10];
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
}
block = sqrt(n);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= block; j++)
ans[j][i % j] += a[i];
for(int i = 1; i <= m; i++) {
scanf("%s",op);
int x,y;
scanf("%d%d",&x,&y);
if(op[0] == 'A') {
int res = 0;
if(x > block) {
for(int i = y; i <= n; i += x) {
res += a[i];
}
printf("%d\n",res);
}
else {
printf("%d\n",ans[x][y]);
}
}
else {
for(int i = 1; i <= block; i++) {
ans[i][x % i] -= a[x];
}
for(int i = 1; i <= block; i++) {
ans[i][x % i] += y;
}
a[x] = y;
}
}
return 0;
}