洛谷P3396哈希冲突

传送门啦

非常神奇的分块大法。

这个题一看数据范围,觉得不小,但是如果我们以 $ \sqrt(x) $ 为界限,数据范围就降到了 $ x < 400 $

我们设数组 $ f[i][j] $ 表示在 % $ i $ 意义下余数是 $ j $ 的数的总和。

然后我们以 $ \sqrt(n) $ 为界限,小于 $ \sqrt(n) $ 的直接调用数组,剩下的暴力查找。修改的话看代码吧,真的不难。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> 
using namespace std;
const int maxn = 150005;

inline int read(){
    char ch = getchar();
    int f = 1 ,x = 0;
    while(ch > '9' || ch < '0'){if(ch == '-')f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
    return x * f;
}

int n,m,a[maxn],x,y;
char flag;
long long f[390][390];//表示在 %i 意义下 余数是 j 的数的总和 

int main(){
    n = read(); m = read();
    for(int i=1;i<=n;i++){
        a[i] = read();
        for(int j=1;j<=sqrt(n);j++)
            f[j][i % j] += a[i];
    }
    while(m--){
        cin >> flag;
        x = read(); y = read();
        if(flag == 'A'){
            if(x * x <= n)
                printf("%lld\n",f[x][y]);
            else {
                int sum = 0;
                for(int j=y;j<=n;j+=x)
                    sum += a[j];
                printf("%d\n",sum);
            }
        }
        else {
            for(int j=1;j<=sqrt(n);j++)
                f[j][x % j] += y - a[x];
            a[x] = y;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Stephen-F/p/9883228.html