P3396 哈希冲突
根号算法![](https://img2018.cnblogs.com/blog/1431596/201811/1431596-20181104214037752-2035982817.png)
这道题暴力92pts。。。
所以说暴力出奇迹!
其实用什么哈希都是在做幌子,要你求的就是从\(k\)位置开始,隔\(p\)个数的数字加起来的和。
我们考虑用一个二维数组存下来,用\(ans[p][k]\)表示模数为\(p\),余数为\(k\)的答案。
如果把所有的模数都处理,跟暴力是没有差别的,甚至还会更劣。
但其实我们只要处理\(\sqrt{n}\)内的模数即可。
小于\(\sqrt{n}\)的我们直接输出数组的值,大于的直接暴力求解。
因为这个\(p\)已经大于了\(\sqrt{n}\),所以我们暴力一次的复杂度是小于\(\sqrt{n}\)的。
所以就搞定了!!
代码:
#include<cstdio>
#include<cmath>
const int maxn = 150005;
int a[maxn], n, m;
int b[400][400];
int read()
{
int ans = 0, s = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
return s * ans;
}
void write(int x)
{
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int main()
{
n = read(), m = read();
int lim = sqrt(n);
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= lim; j++)
{
b[j][i % j] += a[i];
}
}
while(m--)
{
char opt; scanf(" %c", &opt);
int x = read(), y = read();
if(opt == 'A')
{
if(x <= lim) printf("%d\n", b[x][y]);
else
{
int res = 0;
for(int i = y; i <= n; i += x)
{
res += a[i];
}
printf("%d\n", res);
}
}
else if(opt == 'C')
{
for(int i = 1; i <= lim; i++)
{
b[i][x % i] = b[i][x % i] - a[x] + y;
}
a[x] = y;
}
}
return 0;
}