P3396 哈希冲突

根号算法

这道题暴力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;
}
posted @ 2018-11-04 21:50  Garen-Wang  阅读(127)  评论(0编辑  收藏  举报