D. CGCDSSQ (gcd&ST表)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. CGCDSSQ (gcd&ST表)相关的知识,希望对你有一定的参考价值。
D. CGCDSSQ (gcd&ST表)
考虑前缀 g c d gcd gcd 是非递增的,若不同最少 / 2 /2 /2 ,所以增加的 g c d gcd gcd 的个数 l o g log log的
所以考虑用 m a p map map 维护前缀进行递推。
#include <bits/stdc++.h>
using namespace std;
int n, q;
map<int,long long> tmp, d, res;
int main() {
scanf("%d",&n);
for(int i = 0, x; i < n; i++) {
scanf("%d",&x);
tmp.clear();
for(auto p: d) tmp[__gcd(x, p.first)] += p.second;
tmp[x]++;
swap(tmp, d);
for(auto p: d) res[p.first] += p.second;
}
scanf("%d",&q);
int x;
while(q--) scanf("%d", &x), printf("%lld\\n", res[x]);
}
此外还可以根据 g c d gcd gcd的非递增性,对每个左端点进行二分,按 g c d gcd gcd相同的一段进行二分,这样变化最多 l o g log log次,然后用个map统计答案即可。
下面的参考代码二分是的最小的第一个不同的gcd位置。
#include <bits/stdc++.h>
using namespace std;
#define maxn 101000
typedef long long LL;
template <typename T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, m;
int a[maxn], lg[maxn], q[maxn];
int f[maxn][25];
map <int, LL> ans;
inline int gcd(int x, int y) { return y ? gcd(y, x % y) : x; }
inline void pre_work() { // 预处理gcd
lg[0] = -1;
for (int i = 1; i <= n; ++i) {
lg[i] = lg[i >> 1] + 1, f[i][0] = a[i];
}
for (int j = 1; j <= 20; ++j) {
for (int i = 1; i <= n - (1 << (j - 1)) + 1; ++i) {
f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
}
inline int query(int l, int r) { // 查询
int t = lg[r - l + 1];
return gcd(f[l][t], f[r - (1 << t) + 1][t]);
}
void solve(int x) { // x 为固定的左端点
int L = x, R = x;
while (R <= n) {
int left = L, right = n;
int g = query(x, L);
while (left <= right) {
int mid = (left + right) >> 1;
if (query(x, mid) == g) left = mid + 1;
else right = mid - 1;
}
R = left;
ans[g] += (LL)R - L;
L = R;
}
}
int main() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i]);
pre_work();
for (int i = 1; i <= n; ++i) solve(i); // 处理左端点
read(m);
for (int i = 1; i <= m; ++i) {
int x; read(x);
printf("%lld\\n", ans[x]);
}
return 0;
}
以上是关于D. CGCDSSQ (gcd&ST表)的主要内容,如果未能解决你的问题,请参考以下文章
D. Pair of Numbers (ST表&二分&双指针)
ST表和倍增算法(Array Stabilization (GCD version)Codeforces Round #717 (Div. 2) D. Cut)