题目地址:
https://www.acwing.com/problem/content/879/
给定 n n n对正整数 a i , b i a_i,b_i ai,bi,对每对数,求一组 x i , y i x_i,y_i xi,yi,使得下式成立: a i x i + b i y i = gcd ( a i , b i ) a_ix_i+b_iy_i=\gcd(a_i,b_i) aixi+biyi=gcd(ai,bi)。
数据范围:
1 ≤ n ≤ 1 0 5 1\le n\le 10^5 1≤n≤105
1 ≤ a i , b i ≤ 2 × 1 0 9 1\le a_i,b_i\le 2\times 10^9 1≤ai,bi≤2×109
也可以用辗转相除法做。当 b = 0 b=0 b=0的时候,显然 ( a , b ) = a (a,b)=a (a,b)=a,那么一组解就是 x = 1 , y = 0 x=1,y=0 x=1,y=0。否则的话,设 d = ( a , b ) d=(a,b) d=(a,b),我们递归求解对于数对 b , a m o d b b, a\mod b b,amodb的一组解 x ′ , y ′ x',y' x′,y′,那么有 b x ′ + ( a m o d b ) y ′ = d bx'+(a\mod b)y'=d bx′+(amodb)y′=d,所以 b x ′ + ( a − ⌊ a b ⌋ b ) y ′ = d a y ′ + ( x ′ − ⌊ a b ⌋ y ′ ) b = d bx'+(a- \lfloor\frac{a}{b}\rfloor b)y'=d\\ ay'+(x'-\lfloor\frac{a}{b}\rfloor y')b=d bx′+(a−⌊ba⌋b)y′=day′+(x′−⌊ba⌋y′)b=d所以原方程的一组解就是 x = y ′ , y = x ′ − ⌊ a b ⌋ y ′ x=y',y=x'-\lfloor\frac{a}{b}\rfloor y' x=y′,y=x′−⌊ba⌋y′。在代码里,我们可以将 x ′ x' x′和 y ′ y' y′的地位互换,这样可以少一次赋值。代码如下:
#include <iostream>
using namespace std;
// x和y传引用,在执行完exgcd这个函数之后,x和y里就存了一组解
void exgcd(int a, int b, int& x, int& y) {
if (!b) {
x = 1, y = 0;
return;
}
// 递归调用的时候,换一下x和y的位置,这样可以少一次赋值
exgcd(b, a % b, y, x);
y -= a / b * x;
}
int main() {
int n;
cin >> n;
while (n--) {
int a, b, x, y;
cin >> a >> b;
exgcd(a, b, x, y);
printf("%d %d\n", x, y);
}
return 0;
}
每次查询时空复杂度 O ( log min { a , b } ) O(\log \min\{a, b\}) O(logmin{ a,b})。