简单公约数算法

E·M·T

定义 (gcd(a,b)) 为整数 (a、b) 的最大公约数。

首先是一些琐碎的性质:

  1. 对于两个数 (p_1^{a_1}p_2^{a_2}cdots p_k^{a_k}、p_1^{b_1}p_2^{b_2}cdots p_k^{b_k}) 来说, (gcd(p_1^{a_1}p_2^{a_2}cdots p_k^{a_k},p_1^{b_1}p_2^{b_2}cdots p_k^{b_k}) = p_1^{min(a_1,b_1)}p_2^{min(a_2,b_2)}cdots p_k^{min(a_k,b_k)})(lcm) 的话类似, 只是 (min) 改成了 (max)

  2. (gcd(a,b)=1 Rightarrow gcd(a,bc)=gcd(a,c)) 对着上面的那条性质很好理解。

  3. (gcd(a,b) = gcd(a-b,b)) , 这个是欧几里得算法的基础; (gcd(a,n) = gcd(a+n,n)) ,这是分号左边那条的推论, 它说明了 (gcd_n(x) = gcd(n,x)) 这个函数是周期性的。

  4. (gcd(dfrac{a}{gcd(a,b)}, dfrac{b}{gcd(a,b)}) = 1), 结合第一条很好理解。

总之结合第一条都很好证, 因为第一条基本包含了 (gcd) 函数的全部信息。

exgcd

首先有个叫Bezout定理的, 意思是 (ax+by=gcd(a,b)) 必定有解, 其中 (a、b) 是给定的常数而 (x、y) 是变量。(不会证)

exgcd 就是求解这个方程的算法:

首先有 (amod b = a - blfloor dfrac ab floor), 其次由于 (gcd(a,b) = gcd(b,amod b)), 那么如果求出 (sf y'b +x'(amod b) = gcd(a,b)) 的解, 就有: (sf y'b +x'(amod b) = y'b +x'(a-blfloor dfrac ab floor) = (y'- x'lfloor dfrac ab floor)b + x'a) , 这就是 (ax+by=gcd(a,b)) 的一个解。

注意这个解一定不是唯一的, 如果求出了一组解 (sf (x_0、y_0)) 那么 ((x_0+kdfrac{b}{gcd(a,b)}, y_0-kdfrac{a}{gcd(a,b)}), quad kinBbb Z) 就是通解, 通解是无限的, 要得到最小正整数解就直接随便求出一个 (x_0) 然后膜上 (dfrac{b}{gcd(a,b)}) 搞成最小正整数就行了。

代码的话可以这样写:

void exgcd(int a,int b,int &x,int &y,int &GCD) {//由于exgcd的算法过程与gcd有重叠, 所以为了方便可以顺便求 a、b的 GCD
    !b ? x=1,y=0,GCD=a : (exgcd(b,a%b,y,x,GCD), y-=x*(a/b));
}

要是不想压行可以这样写,:

void exgcd(int a,int b,int &x,int &y,int &GCD) {
    if(b==0) {GCD=a; x=1; y=0; return; }
    exgcd(b, a%b, y, x, GCD);
    y -= x*(a/b);
}

个人觉得压行更利于查错, 虽然这种算法不应该出错。

类欧

最基本的模型: (sf sol(n,A,B,C) = sum_{i=1}^nlfloor dfrac{Ai+B}{C} floor)

待补待补。

我得先读一下具体数学第三章再学这个算法。

明年不退役的话再说吧。

原文地址:https://www.cnblogs.com/tztqwq/p/13740527.html