CF1207F. Remainder Problem 暴力分治
Notes
给定一个50万大小的一维数组,有以下两个操作,进行最多50万次询问
-
1 x x x y y y 把
a[x]
加上 y y y -
2 x x x y y y 求在 a a a数组中所有 i m o d x = y i mod x =y imodx=y的
a[i]
的和
复杂度证明 -
假设以 B B B为界,预处理出模数小于 B B B的答案,查询时如果模数小于 B B B就直接返回。预处理 B B B矩阵所用时间为 O ( B ) O(B) O(B)
-
模数大于 B B B,暴力计算所用时间为 O ( N B ) → 求 每 个 数 消 耗 的 时 间 , 这 里 不 要 省 去 B O(\frac{N}{B})\to 求每个数消耗的时间,这里不要省去B O(BN)→求每个数消耗的时间,这里不要省去B
每个查询的复杂度可以表示为
O
(
N
B
+
B
)
→
O
m
i
n
=
M
i
n
(
N
B
+
B
)
⟺
N
B
+
B
≥
N
B
×
B
=
N
(
N
B
=
B
时
)
O(\frac{N}{B}+B) \to O_{min}=Min(\frac{N}{B}+B) \iff\frac{N}{B}+B\geq \sqrt{\frac{N}{B}\times B}= \sqrt{N} (\frac{N}{B}=B时)
O(BN+B)→Omin=Min(BN+B)⟺BN+B≥BN×B=N(BN=B时)
所以总复杂度为
O ( q × N ) O(q\times \sqrt{N}) O(q×N)
Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
const ll maxn = 2e6 + 7;
int a[600000];
int ans[800][800];//记录所有k=(1~5e5)中所有a[k]%i==j的和
int main() {
ios::sync_with_stdio(false);
int q, t, x, y;
cin >> q;
while (q--) {
cin >> t >> x >> y;
if (t == 1) {
a[x] += y;
for (long long i = 1; i <= 750; ++i) {
ans[i][x % i] += y;
}
} else if (t == 2) {
if (x <= 750) cout << ans[x][y] << '\n';
else {
ll tmp = 0;
for (long long i = y; i <= 500000; i += x) {
tmp += a[i];
}
cout << tmp << '\n';
}
}
}
return 0;
}