1. 程式人生 > >洛谷P3396雜湊衝突

洛谷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;
}