abc254 F - Rectangle GCD

题意:

给定等长的正整数组 \(a[],b[]\),它们确定了一个矩阵 \(A_{i,j} = a_i+b_j\)\(q\) 次询问,回答矩阵中一个矩形区域内所有数的 \(\gcd\)

\(n,q\le 2e5\)

思路:

差分,绝对值,st表区间 gcd
\(\gcd(a_1, a_2, a_3, \cdots ) = \gcd(a_1, a_2-a_1, a_3-a_2, \cdots )\)

写代码注意套个绝对值

证明:

\(\gcd(x,y) = \gcd (x-y, y), x>y\) 对大小有要求,不妨换条路走

\(g|a,g|b\)\(g|a+b, g|abs(a-b)\),所以等式两边的因数相同

题解见 https://zhuanlan.zhihu.com/p/524503584

const signed N = 3e5 + 5;
int n, q, a[N], b[N];
int logn[N], f[N][19], g[N][19];
void initlog() {
    logn[1] = 0, logn[2] = 1;
    for(int i = 3; i < N; i++)
        logn[i] = logn[i >> 1] + 1;
}
void pre(int f[N][19]) {
    for(int j = 1; j < 19; j++)
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = __gcd(f[i][j - 1], f[i+(1<<(j-1))][j - 1]);
}
int ask(int f[N][19], int l, int r) {
    if(l > r) return 0;
    int k = logn[r - l + 1];
    return __gcd(f[l][k], f[r+1-(1<<k)][k]);
}
void sol() {
    initlog(); //预处理log2
    cin >> n >> q;
    for(int i = 1; i <= n; i++)
        cin >> a[i], f[i][0] = abs(a[i] - a[i - 1]);
    for(int i = 1; i <= n; i++)
        cin >> b[i], g[i][0] = abs(b[i] - b[i - 1]);
    pre(f), pre(g);
    while(q--) {
        int h1, h2, w1, w2;
        cin >> h1 >> h2 >> w1 >> w2;
        int ans = __gcd(ask(f, h1 + 1, h2), ask(g, w1 + 1, w2));
        cout << __gcd(ans, a[h1] + b[w1]) << '\n';
    }
}
posted @ 2023-01-12 17:25  Bellala  阅读(40)  评论(0)    收藏  举报