题目描述
输入
输出
样例输入
3 10
样例输出
7
提示
对于 100%的数据,2 ≤a, b≤ 2,000,000,000。
思路:exgcd的应用——求解不定方程、求解线性同余方程
-----------------------------------------------------------------------------
下面给出关于ecgcd的详解与模板:(以下讨论的数全为整数)
问题1:给出方程 ax+by=gcd(a,b) ,求解满足方程的x,y的一组解(求解不定方程)
解: 构造一个相同形式的方程——bx1+(a%b)y1=gcd(b,a%b)
联立上述两个方程:因为由欧几里得定理有gcd(a,b)=gcd(b,a%b),所以ax+by=bx1+(a%b)y1
因为a%b=a-a/b*b,带入上式并整理得ax+by=ay1+b(x1-a/b*y1)
对比等式左右两边得x=y1 , y=x1-a/b*y1
因此,若知道满足方程bx1+(a%b)y1=gcd(b,a%b)的x1,y1的一组解,就可以得出x,y的一组解
同理关于方程bx1+(a%b)y1=gcd(b,a%b)的求解也可以用同样的方法由相应的x2,y2得出
如此递归下去,当递归到最底层b=0时,显然方程的一组解为x=1,y=0
得到这组解后,便可以回溯得到最顶层方程即ax+by=gcd(a,b)的一组解了。
引理:存在 x , y 使得 ax+by=gcd(a,b)
上述解法,我们可以用递归的方法来实现。
void exgcd(ll a,ll b){//x,y为两参数,a,b为两参数的系数 if(b==0) y=(x=1)-1;//x,y为全局变量 else{ exgcd(b,a%b); ll tmp=x; x=y; y=tmp-a/b*y; } }
上述代码实现了求方程ax+by=gcd(a,b)的一组解x和y,可以由这一组解得到方程的其他多组解:(设x0,y0为一组已知解,x,y为通解)
x=x0+b/gcd(a,b)*k
y=y0+a/gcd(a,b)*k (其中k为整数)
将通解带入原方程即可验证。
问题2:给出方程 ax+by=r,求解满足方程的x,y的一组解(求解不定方程)
解: 当r%gcd(a,b)!=0时,方程无整数解
当r%gcd(a,b)==0时,先利用exgcd求出方程ax+by=gcd(a,b)的一组解x0,y0,则有ax+by=r的一组解为x1=x0*r/c,y1=y0*r/c
原方程的通解为 x=x1+b/gcd(a,b)*k
y=y1+a/gcd(a,b)*k
问题3:求关于 模方程 ax%b=c(ax=c(mod b))的解x(求解线性同余方程)
解:方程转换为 ax+by=c ,即利用exgcd求不定方程的解x,y(最后只需要x的值)
原方程的通解为x=x0+b/gcd(a,b)*k(其中x0为ax%b=c的其中一解)
设s=b/gcd(a,b),则 x 的最小正整数解为 (x1%s+s)%s
-----------------------------------------------------------------------------
AC代码:
#include <iostream> #include<cstdio> #define ll long long using namespace std; ll x,y; void exgcd(ll a,ll b){ if(b==0) y=(x=1)-1; else{ exgcd(b,a%b); ll tmp=x; x=y; y=tmp-a/b*y; } } int main() { ll a,b; scanf("%lld%lld",&a,&b); exgcd(a,b); while(x<=0) x+=b; printf("%lld\n",x); return 0; }