首页 > 其他分享 >P10463 Interval GCD

P10463 Interval GCD

时间:2024-07-27 22:51:22浏览次数:7  
标签:GCD val int ll Interval mid P10463 最大公约数 gcd

P10463 Interval GCD

原题传送门

思路

首先,有个性质:对于任意多整数,它们的最大公约数与它们的差分序列的最大公约数相同,可以通过以下证明。

\(\forall a, b, c \in \mathbb{N} \text{,有} \gcd(a, b, c) = \gcd(a, b - a, c - b)\)
\(\text{证明:设} d \mid a, d \mid b, d \mid c\)
\(a = k_1 d, b = k_2 d, c = k_3 d, (k_1, k_2, k_3 \in \mathbb{N})\)
\(\because b - a = (k_2 - k_1)d, c - b = (k_3 - k_2)d\)
\(\therefore d \mid {b - a}, d \mid {c - b}\)

易发现,把 \(3\) 个数拓展到任意多整数,该性质都是成立的。

所以可以构造 \(A\) 的差分序列 \(B\),用线段树来维护 \(B\) 的区间最大公约数,询问区间最大公约数就可以通过求 \(A_l\) 与 \(B\) 中 \(l + 1\) 到 \(r\) 区间的最大公约数来解决。

这样,在执行操作 1 时,就只用让 \(B_l + d\) , \(B_{r + 1} - d\) ,不会改变中间的数,也就不用把区间中每个数都再取出来求最大公约数了!

此外因为询问需要用到数列 \(A\) 中的值,可以用树状数组来维护 \(A\) 中的数值。

有一点需要注意,差分序列的可能有负数,所以询问时要取绝对值

代码

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

const int N = 5e5 + 5;

#define ll long long
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define mid ((l + r) >> 1)
#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)

int n, m;
ll a[N], tr[N << 2], b[N], c[N];

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a;}
void up(int rt) { tr[rt] = gcd(tr[ls], tr[rs]); }

void build(int rt, int l, int r) {
    if (l == r) { tr[rt] = b[l]; return; }
    build(ls, l, mid), build(rs, mid + 1, r);
    up(rt);
}

void update(int rt, int l, int r, int x, ll v) {
    if (l == r){ tr[rt] += v; return; }
    if (x <= mid) update(ls, l, mid, x, v);
    else update(rs, mid + 1, r, x, v);
    up(rt);
}

ll query(int rt, int l, int r, int L, int R) {
    if (L <= l && r <= R) return abs(tr[rt]);
    ll val = 0;
    if (mid >= L) val = gcd(val, query(ls, l, mid, L, R));
    if (mid < R) val = gcd(val, query(rs, mid + 1, r, L, R));
    return abs(val);
}

ll sum(int x) {
    ll y = 0;
    for (; x; x -= x & -x) y += c[x];
    return y;
}

void add(int x, ll y) { for (; x <= n; x += x & -x) c[x] += y; }

int main()
{
    scanf("%d%d", &n, &m);
    LF(i, 1, n) {
        scanf("%lld", &a[i]);
        b[i] = a[i] - a[i - 1];
    }

    build(1, 1, n);

    LF(i, 1, m) {
        int l, r;
        char s[2];
        scanf("%s%d%d", s, &l, &r);

        if (s[0] == 'Q') {
            ll al = a[l] + sum(l);
            ll val = l < r ? query(1, 1, n, l + 1, r) : 0;
            printf("%lld\n", gcd(al, val));
        }
        else {
            ll d;
            scanf("%lld", &d);
            update(1, 1, n, l, d);
            if (r < n) update(1, 1, n, r + 1, -d);
            add(l, d);
            add(r + 1, -d);
        }
    }
    return 0;
}

标签:GCD,val,int,ll,Interval,mid,P10463,最大公约数,gcd
From: https://www.cnblogs.com/faruzan/p/18327646

相关文章

  • 基础数论 欧拉定理与exgcd
    欧拉定理:若正整数\(a,n\)互质,则\(a^{\varphi(p)}\equiv1(\bmodp)\)推论(扩展欧拉定理):\[a^b\equiv\begin{cases}a^{b\\bmod\\varphi(p)}\\\\\\\\\\gcd(a,p)=1\\a^b\\\\\\\\\\\\\\\\\\\\\\gcd(a,p)!......
  • 快速 GCD
    预处理GCD\(O(n)\)预处理,\(O(1)\)查询两个小于\(n\)的数的快速\(\gcd\)。引理对于任意正整数\(n\),可以将\(n\)写成\(n=abc\),满足\(a,b,c\)任意一个小于\(\sqrt{n}\)或为质数。考虑归纳,首先对于\(1\),显然成立。否则,设\(n\)的最小质因子为\(p\),设\(\dfrac{n......
  • gcd之和(一维)
    gcd之和求∑i=1n......
  • 二元一次不定方程(Exgcd)(更方便的解法)
    扩展欧几里得算法(Exgcd)裴蜀定理对于任意一组整数\(a,b\),存在一组整数\(x,y\),满足\(ax+by=\gcd(a,b)\)。Proof:考虑数学归纳法。当\(b=0\)时,由于\(\gcd(a,0)=a\),则对于\(ax+0y=a\)这个不定方程,\(x=1\),\(y\)取任意整数。假设存在一组整数\(x,y\),满足$bx+(a\bmodb)y......
  • 推式子——拓展欧几里德算法exgcd
    试求方程\(ax+by=\gcd(a,b)\)的一组整数解,其中\(a\)和\(b\)是给定的数提前准备好一个式子:辗转相除法\[\gcd(a,b)=\gcd(b,a\bmodb)\]同时我们可以注意到,\(\bmod\)的等价版本:\[a\bmodb=a-b\lfloor\frac{a}{b}\rfloor\]开始推式子首先考虑\(b=0\)的情况,因为......
  • 对等式 gcd(x,y)=x⊕y 的一点思考
    前日打算法赛时遇到了一个等式\(\gcd(x,y)=x\oplusy\),要求给定\(x\)在最短时间内求得满足条件的一个\(y\)。赛中使用了暴力找规律大法过了,赛后决定认真严谨证明一下满足条件的\(y\)的相关性质,于是有了这篇文章(Part1:\(x\)是奇数先介绍【异或配对性定理】:若\(......
  • exgcd
    裴蜀定理对于任意整数\(a,b\)都存在整数\(x,y\),使得\(ax+by=gcd(a,b)\)扩展欧几里得算法(exgcd)设整数\(a,b,x,y\)满足\(ax+by=gcd(a,b)\)若\(b=0\),则\(x=1\),\(y\)取任意整数若\(b>0\)\[ax+by=gcd(a,b)\]\[=gcd(b,a\mod\b)\]\[=bx_0+(a\mod\b)y_0\]\[=bx_0+(a-......
  • iOS开发基础133-GCD相关
    先看一段代码,这是项目中图片上传的一部分代码。//开启线程组上传图片dispatch_group_tgroup=dispatch_group_create();[self.selectedPhotosenumerateObjectsUsingBlock:^(UIImage*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop){dispatch_gro......
  • 扩展欧几里得算法(exGcd)
    扩展欧几里得算法(ExtendedEuclideanalgorithm,EXGCD),常用于求\(ax+by=c\)的一组可行解。过程设\(ax_1+by_1=\gcd(a,b)\)\(bx_2+(a\modb)y_2=gcd(b,a\modb)\)由欧几里得算法:\(\gcd(a,b)=gcd(b,a\modb)\)所以:\(ax_1+by_1=bx_2+(a\modb)y_2\)又因为:\(a\mod......
  • Divide Interval 题解
    背景太逊了,调了三次才调出来,所以写篇题解寄念。LC好睿智题意给你两个数\(a,b\),现在要从\(a\)跑到\(b\),每次可以将当前的\(a\)拆分成\(2^n\timesm(n,m\inN)\)的形式,并将它变成\(2^n\times(m+1)\)。问最少变几次能跑到\(b\),输出次数和每次变化前后\(a\)的值。分......