GCD CRT 逆元

扩展欧几里得算法（Exgcd）用于求解方程 $ax + by = \gcd(a, b)$ 的整数解 $x$ 和 $y$，同时返回 $a$ 和 $b$ 的最大公约数。以下是代码的逐层解释：

### 递归终止条件
当 $b = 0$ 时，方程为 $a \cdot 1 + 0 \cdot 0 = a$，此时：
- $x = 1$, $y = 0$
- 直接返回 $a$（最大公约数）

### 递归过程
1. **递归调用**：计算 $\gcd(b, a \% b)$，得到解 $x'$ 和 $y'$，满足：
   $$
   b \cdot x' + (a \% b) \cdot y' = \gcd(b, a \% b)
   $$
   根据欧几里得算法，$\gcd(a, b) = \gcd(b, a \% b)$。

2. **转换解**：将递归结果的解 $x'$ 和 $y'$ 转换为当前层的解 $x$ 和 $y$。利用 $a \% b = a - \lfloor a/b \rfloor \cdot b$，原方程可重写为：
   $$
   a \cdot y' + b \cdot (x' - \lfloor a/b \rfloor \cdot y') = \gcd(a, b)
   $$
   因此：
   - $x = y'$
   - $y = x' - \lfloor a/b \rfloor \cdot y'$

### 代码步骤
- **保存递归前的 $x$**：`int t = x`（此时 $x = x'$）。
- **更新 $x$**：`x = y`（将 $x$ 设为 $y'$）。
- **更新 $y$**：`y = t - (a / b) * y`（计算 $y = x' - \lfloor a/b \rfloor \cdot y'$）。

### 示例分析
以 $a = 30$, $b = 12$ 为例：
1. 递归至 $\gcd(6, 0)$，返回 $x = 1$, $y = 0$, $\gcd = 6$。
2. 回溯到 $\gcd(12, 6)$，计算 $x = 0$, $y = 1$，满足 $12 \cdot 0 + 6 \cdot 1 = 6$。
3. 回溯到 $\gcd(30, 12)$，计算 $x = 1$, $y = -2$，满足 $30 \cdot 1 + 12 \cdot (-2) = 6$。

### 总结
代码通过递归分解问题，逐步缩小规模。每次递归后，利用子问题的解 $x'$ 和 $y'$ 推导当前层的解 $x$ 和 $y$，最终得到满足 $ax + by = \gcd(a, b)$ 的整数解。

好的，下面是对这段 C++ 代码的逐行详细解释：

```cpp
int Exgcd(int a, int b, int &x, int &y) {
```
- 定义了一个名为 `Exgcd` 的函数。
- 函数参数包括两个整数 `a` 和 `b`，以及两个引用参数 `x` 和 `y`。
- `x` 和 `y` 用来输出结果，表示满足方程 $ ax + by = \text{GCD}(a, b) $ 的系数。

```cpp
  if (!b) {
```
- 检查 `b` 是否为 0。`!b` 表示 `b` 为 0 的时候，条件为真。

```cpp
    x = 1;
    y = 0;
    return a;
```
- 如果 `b` 是 0，则最大公约数是 `a`，同时根据贝祖定理，我们可以得到系数：
  - 设置 `x = 1`（表示 $a \cdot 1$），
  - 设置 `y = 0`（表示 $b \cdot 0$）。
- 返回 `a`，也就是最大公约数。

```cpp
  }
```
- 结束了对 `b` 是否为 0 的检查。

```cpp
  int d = Exgcd(b, a % b, x, y);
```
- 递归调用 `Exgcd` 函数，参数为 `b` 和 `a % b`（即 `a` 除以 `b` 的余数）。
- 这个递归调用会继续进行，直到 `b` 为 0，返回的最大公约数会被存储在 `d` 中，同时计算得到的 $x$ 和 $y$ 值也会在递归返回的过程中更新。

```cpp
  int t = x;
```
- 创建一个临时变量 `t`，存储 `x` 的当前值。这个值在接下来的代码中会被更新。

```cpp
  x = y;
```
- 将 `y` 的值赋给 `x`。在执行 `Exgcd(b, a % b)` 时，新的 $x$ 是旧的 $y$。

```cpp
  y = t - (a / b) * y;
```
- 更新 `y` 的值。根据公式：
  - 我们把旧的 `y` 乘以 $ -\left(\frac{a}{b}\right) $（即取整运算向下取整），再减去 `t`（旧的 `x` 值）。
- 这个步骤是用于反向计算贝祖系数。

```cpp
  return d;
```
- 返回最大公约数 `d`。

整个函数的目的是找到两个数 $a$ 和 $b$ 的最大公约数，同时计算出系数 $x$ 和 $y$，使得 $ax + by = \text{GCD}(a, b)$ 成立。这个算法在许多数字和代数问题中都非常有用，尤其是在计算模反元素和求解线性同余方程时。

好的！以下是逐行注释的 **扩展欧几里得算法（Exgcd）** 的 C++ 代码解释，帮助理解递归过程和解的推导逻辑：

```cpp
int Exgcd(int a, int b, int &x, int &y) {
    // 递归终止条件：当 b = 0 时，gcd(a, 0) = a
    if (!b) {
        // 此时方程 ax + 0*y = a，显然 x = 1, y 可以是任意整数（此处设为 0）
        x = 1;   // 基础解 x = 1
        y = 0;   // 基础解 y = 0（为了后续递归回溯时计算方便）
        return a; // 返回最大公约数
    }

    // 递归调用：计算 gcd(b, a % b)，并得到对应的解 x' 和 y'
    // 注意：这里的 x 和 y 会被递归过程不断修改，最终得到的是下一层的解
    int d = Exgcd(b, a % b, x, y);

    // 保存递归返回后的 x（此时 x 已经是下一层的解 x'）
    int t = x; 

    // 当前层的 x 等于下一层的 y'
    // 根据公式推导，x = y'
    x = y; 

    // 当前层的 y 等于下一层的 x' - (a / b) * y'
    // 公式推导：y = x' - floor(a / b) * y'
    y = t - (a / b) * y; 

    // 返回最大公约数（递归过程中一直传递 d，最终返回给最外层）
    return d;
}
```

---

### **关键步骤图解**
假设输入 `a = 30`, `b = 12`，递归过程如下：

1. **第一层递归** `Exgcd(30, 12, x, y)`:
   - 计算 `a % b = 30 % 12 = 6`
   - 进入第二层递归 `Exgcd(12, 6, x, y)`

2. **第二层递归** `Exgcd(12, 6, x, y)`:
   - 计算 `a % b = 12 % 6 = 0`
   - 进入第三层递归 `Exgcd(6, 0, x, y)`

3. **第三层递归** `Exgcd(6, 0, x, y)`:
   - 终止条件触发：`x = 1`, `y = 0`, 返回 `d = 6`

4. **回溯到第二层** `Exgcd(12, 6, x, y)`:
   - `t = x = 1`（保存下一层的 x' = 1）
   - `x = y = 0`（当前层 x = y' = 0）
   - `y = t - (12/6)*y = 1 - 2*0 = 1`（当前层 y = 1）
   - 返回 `d = 6`

5. **回溯到第一层** `Exgcd(30, 12, x, y)`:
   - `t = x = 0`（保存下一层的 x' = 0）
   - `x = y = 1`（当前层 x = y' = 1）
   - `y = t - (30/12)*y = 0 - 2*1 = -2`（当前层 y = -2）
   - 返回 `d = 6`

最终得到解：`x = 1`, `y = -2`，满足 `30*1 + 12*(-2) = 6`（即 gcd(30, 12) = 6）。

---

### **核心公式推导**
递归过程基于以下恒等式：
$$
\gcd(a, b) = \gcd(b, a \% b)
$$
假设递归后得到的解为 $ x' $ 和 $ y' $，满足：
$$
b \cdot x' + (a \% b) \cdot y' = \gcd(b, a \% b)
$$
利用 $ a \% b = a - \lfloor a/b \rfloor \cdot b $，可重写为：
$$
a \cdot y' + b \cdot \left( x' - \lfloor a/b \rfloor \cdot y' \right) = \gcd(a, b)
$$
因此，当前层的解为：
$$
x = y', \quad y = x' - \lfloor a/b \rfloor \cdot y'
$$

---

### **总结**
- **递归逻辑**：通过不断缩小问题规模（`a → b`, `b → a%b`），直到 `b = 0` 时终止。
- **解的回溯**：利用递归返回的解 `x'` 和 `y'`，推导当前层的解 `x` 和 `y`。
- **变量交换**：通过临时变量 `t` 保存中间值，确保计算顺序正确。

这个算法高效地求解了 **贝祖等式（Bézout's identity）** 的整数解，同时计算最大公约数。