P4549 【模板】裴蜀定理、P1516 青蛙的约会(扩展欧几里得方程)、P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

P4549 【模板】裴蜀定理

裴蜀定理

裴蜀定理该定理阐述了两个非零整数的最大公约数(Greatest Common Divisor, GCD)可以通过这两个数的线性组合来表达。具体地,对于任意两个非零整数a和b,存在整数x和y,使得:ax+by=gcd(a,b),这里的gcd(a,b)表示a和b的最大公约数。

换句话说,a和b的最大公约数能够以a和b的整数倍的线性组合的形式出现。更进一步,这样的x和y不仅存在,而且可以有无限多个解。

裴蜀定理的一个重要应用是在求解不定方程ax + by = cax+by=c时,如果c是a和b最大公约数的倍数,那么该方程就有整数解;否则,没有整数解。

例如,考虑a=12和b=15,我们知道\gcd(12, 15)=3gcd(12,15)=3,则存在x和y使得12x + 15y = 312x+15y=3。实际上,一组可能的解是x=-1x=−1和y=1y=1,因为12(-1) + 15(1) = 312(−1)+15(1)=3。

裴蜀定理的证明通常涉及到欧几里得算法(辗转相除法),这个算法也是计算两个整数最大公约数的有效方法。在计算最大公约数的过程中,实际上也可以找到满足裴蜀等式的x和y的值。这种寻找x和y的方法被称为扩展欧几里得算法(Extended Euclidean Algorithm)。

题目描述

P4549 【模板】裴蜀定理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

运行代码

#include<iostream>
using namespace std;
#include<cmath>
typedef long long ll;
ll n, a, s;
ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main() {
	cin >> n;
	for (ll i = 1; i <= n; i++) {
		cin >> a;
		s = gcd(s, abs(a));
	}
	cout << s;
	return 0;
}

代码思路

  1. 输入处理:

    • 首先读入一个整数n,表示序列中整数的个数。
    • 接下来读入n个整数,存储在变量a中,并依次用这些值更新gcd的结果。
  2. 辗转相除法实现:

    • 定义了一个gcd函数,接收两个long long类型的参数ab
    • gcd函数内部,递归调用自身,直到b变为0,此时返回a作为两数的最大公约数。
    • 这里的递归终止条件return b == 0 ? a : gcd(b, a % b);正是辗转相除法的核心,即不断用较小的数去除较大的数,直到余数为0,此时的除数就是最大公约数。
  3. 最大公约数的计算:

    • main函数中,使用变量s来保存序列中所有整数的最大公约数,初始值未知,但随着循环进行,s将被更新为当前已读取的所有整数的最大公约数。
    • 循环遍历每一个输入的整数a,调用gcd函数更新s的值,即s = gcd(s, abs(a));。这里使用abs函数是为了确保即使输入中有负数,也能正确计算其绝对值的GCD。
  4. 输出结果:循环结束后,s包含了整个序列的最大公约数,将其输出。

P1516 青蛙的约会(扩展欧几里得方程)

题目描述

P1516 青蛙的约会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

运行代码

#include <iostream>
typedef long long ll;
using namespace std;
int ex_gcd(ll a, ll b, ll& x, ll& y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    ll nx, ny;
    ll ans = ex_gcd(b, a % b, nx, ny);
    x = ny;
    y = nx - (a / b) * ny;
    return ans;
}

ll gcd(ll a, ll b) { 
    return b ? gcd(b, a % b) : a; 
}
signed main() {
    ll x, y, n, m, L;
    cin >> x >> y >> m >> n >> L;
    ll x_, y_;
    ll a = m - n;
    ll b = L;
    ll c = y - x;
    if (a < 0) {
        a = -a;
        c = -c;
    }
    ll g = ex_gcd(a, b, x_, y_);
    if (c % g) {
        cout << "Impossible\n";
        return 0;
    }
    x_ = x_ * c / g;
    cout << (x_ % (b / g) + (b / g)) % (b / g);
    return 0;
}

代码思路

  1. 扩展欧几里得算法 (ex_gcd 函数):

    • 此函数计算两个整数 aa 和 bb 的最大公约数(GCD),同时找到整数 xx 和 yy,使得 ax + by = gcd(a, b)ax+by=gcd(a,b)。
    • 当 b = 0b=0 时,直接返回 aa 并设置 x = 1, y = 0x=1,y=0。
    • 否则,递归调用 ex_gcd(b, a % b) 并更新 xx 和 yy 的值。
    • 返回 gcd(a, b)gcd(a,b)。
  2. 辗转相除法 (gcd 函数):一个简化的 GCD 计算函数,使用递归实现辗转相除法。

  3. 主程序 (main 函数):

    • 读取输入:x, y, m, n, Lx,y,m,n,L。
    • 设置 a = m - na=m−n 和 b = Lb=L,以及 c = y - xc=y−x。
    • 如果 a < 0a<0,则调整 aa 和 cc 的符号,确保 a > 0a>0,这是因为 GCD 不受正负号的影响。
    • 调用 ex_gcd 函数计算 aa 和 bb 的 GCD 并找到对应的 x'x′ 和 y'y′。
    • 检查 cc 是否能被 gcd(a, b)gcd(a,b) 整除,如果不能,则无解,输出 "Impossible"。
    • 如果可整除,计算 x' = x' \cdot c / gcd(a, b)x′=x′⋅c/gcd(a,b),这是满足原方程的一个特解。
    • 输出满足条件的最小非负整数解 tt,即 (x' \mod (b / gcd(a, b)))(x′mod(b/gcd(a,b)))。这里使用模运算找到满足条件的最小非负解。

P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

题目描述

P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

运行代码

#include <iostream>
#include <cstring>
#include <algorithm>

typedef long long LL;

// 扩展欧几里得算法
LL exgcd(LL a, LL b, LL &x, LL &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, x, y);
    LL temp = x;
    x = y;
    y = temp - a / b * y;
    return d;
}

// 中国剩余定理
LL CRT(LL m[], LL r[], int n) {
    LL M = 1, ans = 0;
    for (int i = 0; i < n; ++i) {
        M *= m[i];
    }
    for (int i = 0; i < n; ++i) {
        LL c = M / m[i];
        LL x, y;
        exgcd(c, m[i], x, y);
        ans = (ans + r[i] * c * x % M) % M;
    }
    return (ans % M + M) % M;
}

int main() {
    int n;
    std::cin >> n;
    LL a[11], b[11];
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i] >> b[i];
    }
    std::cout << CRT(a, b, n) << std::endl;
    return 0;
}

代码思路

exgcd 函数

  • 目的是求解两个数 a 和 b 的最大公约数 d ,同时求出满足 ax + by = d 的 x 和 y 值。
  • 通过递归的方式,先处理 b == 0 的情况,直接设置 x = 1y = 0 并返回 a 作为最大公约数。
  • 否则,先计算 b 和 a % b 的扩展欧几里得结果,然后通过计算更新 x 和 y 的值。

CRT 函数

  • 用于求解中国剩余定理问题。
  • 首先计算所有模数 m[i] 的乘积 M 。
  • 然后对于每个方程,计算 c = M / m[i] ,再通过 exgcd 求出 c 和 m[i] 的解 x 和 y ,计算出当前方程的贡献值 r[i] * c * x % M ,累加到 ans 中。
  • 最后对 ans 进行取模处理,得到最终结果。

main 函数

  • 读取输入的方程个数 n 。
  • 读取每个方程的模数 a[i] 和余数 b[i] 。
  • 调用 CRT 函数计算结果并输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值