前言
这题 trick 就是更相减损术:\(\gcd\{a_1, a_2, a_3, \cdots, a_n\} = \gcd\{a_1, a_2 - a_1, a_3 - a_2, \cdots, a_n - a_{n-1}\}\)。
思路
有了这个 trick 之后这题就好做了。并不需要其他题解一样画表格,化简式子就行,过程并没有难点。
\[\begin{aligned} \text{answer} & = \gcd\limits_{i=x1}^{x2}\Big(\normalsize\gcd\limits_{j=y_1}^{y_2} (a_i + b_j)\Big)\normalsize \\ & = \gcd\limits_{i=x1}^{x2}\Big(\gcd\{ a_i + b_{y_1}, a_i + b_{y_1+1}, a_i + b_{y_1+2}, \cdots, a_i + b_{y_2}\}\Big)\normalsize \\ & = \gcd\limits_{i=x1}^{x2}\Big(\gcd\{ a_i + b_{y_1}, \color{red}b_{y_1+1}-b_{y_1}, b_{y_1+2}-b_{y_1+1}, \cdots, b_{y_2}-b_{y_2-1}\color{black}\}\Big)\normalsize \\ & = \gcd\Big(\normalsize\color{red}b_{y_1+1}-b_{y_1}, b_{y_1+2}-b_{y_1+1}, \cdots, b_{y_2}-b_{y_2-1}\color{black}, \color{blue}\gcd\limits_{i=x_1}^{x_2}(a_i+b_{y_1})\color{black} \Big)\normalsize \\ & = \gcd\Big(\normalsize\color{red}\gcd\limits_{j=y_1+1}^{y_2} (b_j-b_{j-1})\color{black}, \color{blue}\gcd\{a_{x_1}+b_{y_1}, a_{y_1+1}-a_{y_1}, \cdots, a_{y_2}-a_{y_2-1}\} \color{black}\Big)\normalsize \\ & = \gcd\Big(\normalsize\color{red}\gcd\limits_{j=y_1+1}^{y_2} (b_j-b_{j-1})\color{black}, \color{blue}a_{x1}+b_{y1}, \gcd\limits_{i=x1+1}^{x2}(a_i-a_{i-1})\color{black}\Big)\normalsize \\ & = \gcd\Big(\normalsize a_{x1}+b_{y1}, \gcd\limits_{i=x1+1}^{x2}(a_i-a_{i-1}), \gcd\limits_{i=y_1+1}^{y_2} (b_i-b_{i-1})\Big)\normalsize \\ \end{aligned} \]综上,只需维护两个 DS,分别支持求 \((a_i - a_{i-1})\) 与 \((b_i - b_{i-1})\) 的区间 gcd。掏一手 ST 表拿下。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#define y1 zltAKIOI
using namespace std;
const int N = 2e5 + 5;
int n, q;
int gcd(int x, int y) {return y == 0 ? x : gcd(y, x % y);}
struct ST {
int gc[N][20];
void build(int a[])
{
for (int i = 1; i <= n; i++) gc[i][0] = abs(a[i] - a[i - 1]);
for (int j = 1; j <= 18; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
gc[i][j] = gcd(gc[i][j - 1], gc[i + (1 << (j - 1))][j - 1]);
}
int query(int l, int r)
{
if (l > r) return 0;
int len = log2(r - l + 1);
return gcd(gc[l][len], gc[r - (1 << len) + 1][len]);
}
} A, B;
int a[N], b[N];
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
A.build(a), B.build(b);
while (q--)
{
int x1, x2, y1, y2;
scanf("%d%d%d%d", &x1, &x2, &y1, &y2);
printf("%d\n", gcd(gcd(A.query(x1 + 1, x2), B.query(y1 + 1, y2)), a[x1] + b[y1]));
}
return 0;
}
希望能帮助到大家!
标签:gcd,limits,color,题解,int,ABC254F,Big,normalsize From: https://www.cnblogs.com/liangbowen/p/17398763.html