题目描述
众所周知,模数的hash会产生冲突。例如,如果模的数p=7
,那么4
和11
便冲突了。
B君对hash冲突很感兴趣。他会给出一个正整数序列value[]
。
自然,B君会把这些数据存进hash池。第value[k]
会被存进(k%p)
这个池。这样就能造成很多冲突。
B君会给定许多个p
和x
,询问在模p
时,x
这个池内数的总和
。
另外,B君会随时更改value[k]
。每次更改立即生效。
保证1<=p<n1<=p<n.
输入输出格式
输入格式:
第一行,两个正整数n,m
,其中n
代表序列长度,m
代表B君的操作次数。
第一行,n
个正整数,代表初始序列。
接下来m
行,首先是一个字符cmd
,然后是两个整数x,y
。
-
若
cmd='A'
,则询问在模x
时,y
池内数的总和。 -
若
cmd='C'
,则将value[x]
修改为y
。
输出格式:
对于每个询问输出一个正整数,进行回答。
输入输出样例
输入样例#1: 复制
10 5
1 2 3 4 5 6 7 8 9 10
A 2 1
C 1 20
A 3 1
C 5 1
A 5 0
输出样例#1: 复制
25
41
11
说明
样例解释
A 2 1
的答案是1+3+5+7+9=25
.
A 3 1
的答案是20+4+7+10=41
.
A 5 0
的答案是1+10=11
.
数据规模
对于10%
的数据,有n<=1000,m<=1000
.
对于60%
的数据,有n<=100000.m<=100000
.
对于100%
的数据,有n<=150000,m<=150000
.
保证所有数据合法,且1<=value[i]<=1000
.
题解:预处理模数为 1-u 余数也为 1-u (u一般取略小于sqrt(n)的数)的所有答案,复杂度为O(n*u)
u = pow(n, 0.40);
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
for(int j=1; j<=u; j++) sum[j][i%j] += a[i];
}
修改时的复杂度为O(u)
void update(int x, int y){
for(int i=1; i<=u; i++) sum[i][x%i] += -a[x] + y;
a[x] = y;
}
当查询的模数x小于等于u时用O(1) 的复杂度得到答案sum[x][y]
当查询的模数x大于u时暴力查询,如下,因为x>u,所以其复杂度略为O( sqrt(n) )
for(int i=y; i<=n; i+=x) ans += a[i];
总复杂度略为O(n*sqrt(n))
AC代码:
#include<bits/stdc++.h>
//#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a, b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f;
const int O = 1e6;
const int mod = 1e7+3;
const int maxn = 1e3 + 5;
const double PI = acos(-1.0);
const double E = 2.718281828459;
const double eps = 1e-8;
int a[maxn * maxn], sum[maxn][maxn]; // sum[i][j] : p % i == j
int n, m, u;
int get_ans(int x, int y){
if(x <= u) return sum[x][y] ;
int ans = 0;
for(int i=y; i<=n; i+=x) ans += a[i];
return ans ;
}
void update(int x, int y){
for(int i=1; i<=u; i++) sum[i][x%i] += -a[x] + y;
a[x] = y;
}
int main(){
scanf("%d%d", &n, &m);
MT(sum, 0); u = pow(n, 0.40); // 由于测试数据原因该题取0.33速度会更快
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
for(int j=1; j<=u; j++) sum[j][i%j] += a[i];
}
while( m -- ){
char c[2]; int x, y;
scanf("%s%d%d", c, &x, &y);
if(c[0] == 'A') printf("%d\n", get_ans(x, y));
if(c[0] == 'C') update(x, y);
}
return 0;
}