CF1207F. Remainder Problem 暴力分治
Notes
给定一个50万大小的一维数组,有以下两个操作,进行最多50万次询问
-
1 xxx yyy 把
a[x]
加上yyy -
2 xxx yyy 求在aaa数组中所有imodx=yi mod x =yimodx=y的
a[i]
的和
复杂度证明 -
假设以BBB为界,预处理出模数小于BBB的答案,查询时如果模数小于BBB就直接返回。预处理BBB矩阵所用时间为O(B)O(B)O(B)
-
模数大于BBB,暴力计算所用时间为O(NB)→求每个数消耗的时间,这里不要省去BO(\frac{N}{B})\to 求每个数消耗的时间,这里不要省去BO(BN)→求每个数消耗的时间,这里不要省去B
每个查询的复杂度可以表示为
O(NB+B)→Omin=Min(NB+B) ⟺ NB+B≥NB×B=N(NB=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;
}