二元一次方程解的个数分析

本文介绍了如何使用裴蜀定理和扩展欧几里得算法解决给定正整数a,b,c下的二元一次方程ax+by=c,并找到符合条件的整数解。通过推导和举例,展示了求解过程和代码实现。
摘要由CSDN通过智能技术生成

前言

在阅读本文前,假设你已经掌握了裴蜀定理,扩展欧几里得算法。

题目描述

给定正整数 a , b , c a, b, c a,b,c,求出二元一次方程 a x + b y = c ax+by=c ax+by=c 满足 0 ≤ x < b 0\le x < b 0x<b 的所有解,其中 1 ≤ a , b , c ≤ 1 0 6 1\le a,b,c\le 10^6 1a,b,c106

推导过程

裴蜀定理:设 a , b a,b a,b 是不全为 0 0 0 的整数,则存在整数 x , y x,y x,y 满足 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)

扩展欧几里得算法:通常用于求 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b) 的一组可行解。

c c c 不能被 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 整除,方程 a x + b y = c ax+by=c ax+by=c 无解。

c = gcd ⁡ ( a , b ) c=\gcd(a,b) c=gcd(a,b),方程 a x + b y = c ax+by=c ax+by=c gcd ⁡ ( a , b ) \gcd(a, b) gcd(a,b) 个解。

略证:

a x + b y = a x + a b gcd ⁡ ( a , b ) + b y − a b gcd ⁡ ( a , b ) = a ( x + b gcd ⁡ ( a , b ) ) + b ( y − a gcd ⁡ ( a , b ) ) \begin{aligned} ax+by &= ax+\frac{ab}{\gcd(a,b)}+by-\frac{ab}{\gcd(a,b)} \\ &= a(x+\frac{b}{\gcd(a,b)})+b(y-\frac{a}{\gcd(a,b)}) \\ \end{aligned} ax+by=ax+gcd(a,b)ab+bygcd(a,b)ab=a(x+gcd(a,b)b)+b(ygcd(a,b)a)

所以方程 a x + b y = c ax+by=c ax+by=c 相邻两个解 x x x 的距离是 b gcd ⁡ ( a , b ) \frac{b}{\gcd(a,b)} gcd(a,b)b,使用扩展欧几里得算法求出一个 x x x 0 ≤ x < b 0\le x < b 0x<b 范围内恰好有 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 个解。

c ≠ gcd ⁡ ( a , b ) c\neq \gcd(a,b) c=gcd(a,b) c c c 能被 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 整除,方程 a x + b y = c ax+by=c ax+by=c 也是有 gcd ⁡ ( a , b ) \gcd(a, b) gcd(a,b) 个解。

略证:

我们已经证明了相邻两个解的距离只跟 a , b a,b a,b 有关,这里 a , b a,b a,b 跟上面一样,所以我们只需要证明 a x + b y = c ax+by=c ax+by=c 存在一组可行的解就好了。

a x 1 + b y 1 = gcd ⁡ ( a , b ) ax_1+by_1=\gcd(a,b) ax1+by1=gcd(a,b),其中 x 1 , y 1 x_1,y_1 x1,y1 是一组可行的解。

方程两边同时乘上 c gcd ⁡ ( a , b ) \frac{c}{\gcd(a,b)} gcd(a,b)c

a c gcd ⁡ ( a , b ) x 1 + b c gcd ⁡ ( a , b ) y 1 = c \frac{ac}{\gcd(a,b)}x_1+\frac{bc}{\gcd(a,b)}y_1=c gcd(a,b)acx1+gcd(a,b)bcy1=c

x 2 = c gcd ⁡ ( a , b ) x 1 x_2=\frac{c}{\gcd(a,b)}x_1 x2=gcd(a,b)cx1 y 2 = c gcd ⁡ ( a , b ) y 1 y_2=\frac{c}{\gcd(a,b)}y_1 y2=gcd(a,b)cy1

a x 2 + b y 2 = c ax_2+by_2=c ax2+by2=c

所以 x 2 , y 2 x_2,y_2 x2,y2 a x + b y = c ax+by=c ax+by=c 的一组可行解,因为方程 a x + b y = c ax+by=c ax+by=c 相邻两个解 x x x 的距离还是 b gcd ⁡ ( a , b ) \frac{b}{\gcd(a,b)} gcd(a,b)b,所以 0 ≤ x < b 0\le x < b 0x<b 范围内恰好有 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 个解。

代码实现

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define all(x) (x).begin(), (x).end()
#define endl '\n'
// #define endl " line in : " << __LINE__ << endl
ostream& operator << (ostream &out, const pii &p) {
  return out << '{' << p.first << ',' << p.second << '}';
}
const int N = 5e5 + 5, INF = 1e17, P = 998244353;
int exgcd(int a, int b, int &x, int &y) {
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  int d = exgcd(b, a % b, x, y);
  int tx = x, ty = y;
  x = ty, y = tx - a / b * ty;
  return d;
}
int a, b, c;
void test() {
  cin >> a >> b >> c;
  int x, y, d = exgcd(a, b, x, y);
  if (c % d != 0) {
    cout << -1 << endl;
    return;
  }
  x = x * (c / d), y = y * (c / d);
  x = (x % (b / d) + (b / d)) % (b / d);
  y = (c - a * x) / b;
  cout << d << endl;
  for (int i = 0; i < d; i++) {
    cout << x << ' ' << y;
    x += b / d, y -= a / d;
  }
}
signed main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  // int T; cin >> T; while (T--)
  test();
  return 0;
}

例题

洛谷 P5656 【模板】二元一次不定方程 (exgcd)

这题需要在满足 x ≥ 1 x\ge 1 x1 y ≥ 1 y \ge 1 y1 的解中,分别找 x x x 最小的解, y y y 最小的解, x x x 最大的解, y y y 最大的解,需要注意的是当 x x x 最小时, y y y 最大;当 y y y 最小时, x x x 最大。

例题代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
#define all(x) (x).begin(), (x).end()
#define endl '\n'
// #define endl " line in : " << __LINE__ << endl
ostream& operator << (ostream &out, const pii &p) {
  return out << '{' << p.first << ',' << p.second << '}';
}
const int N = 5e5 + 5, INF = 1e17, P = 998244353;
int exgcd(int a, int b, int &x, int &y) {
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  int d = exgcd(b, a % b, x, y);
  int tx = x, ty = y;
  x = ty, y = tx - a / b * ty;
  return d;
}
int a, b, c;
void test() {
  cin >> a >> b >> c;
  int x, y, d = exgcd(a, b, x, y);
  if (c % d != 0) {
    cout << -1 << endl;
    return;
  }
  // cout << d << ' ' << x << ' ' << y << endl;
  a /= d, b /= d, c /= d;
  x *= c, y *= c;
  x = (x % b + b) % b;
  if (x == 0) x += b;
  y = (c - a * x) / b;
  int y2 = (y % a + a) % a;
  if (y2 == 0) y2 += a;
  int x2 = (c - b * y2) / a;
  // cout << x << ' ' << y << ' ' << x2 << ' ' << y2 << endl;
  if (x >= 1 && y >= 1) {
    cout << (x2 - x) / b + 1 << ' ' << x << ' ' << y2 << ' ' << x2 << ' ' << y << endl;
  }
  else {
    cout << x << ' ' << y2 << endl;
  }
}
signed main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int T; cin >> T; while (T--)
  test();
  return 0;
}

感谢你阅读本文,请收下这只可爱的刻晴。

在这里插入图片描述

  • 31
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值