洛谷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
",f[x][y]);
			else {
				int sum = 0;
				for(int j=y;j<=n;j+=x)
					sum += a[j];
				printf("%d
",sum);
			}
		}
		else {
			for(int j=1;j<=sqrt(n);j++)
				f[j][x % j] += y - a[x];
			a[x] = y;
		}
	}
	return 0;
}
顺风不浪,逆风不怂。
原文地址:https://www.cnblogs.com/Stephen-F/p/9883228.html