暑假训练5之同余方程及扩展问题(扩展欧几里得)

求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解。

ax≡1(mod b)等价于ax+by=1;

同理ax≡c(mod b)等价于ax+by=c;

这样的题都是先求ax+by=gcd(a,b)(扩展欧几里得可求x,y,gcd(a,b),代码如下)

求出的x,y然后乘上c/gcd(a,b)就是所求一个特解;

b = b / gcd(a,b),然后(x%b+b)%b就是最小正整数解

第一种做法:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL a,b,t,x,y;//ax+by=t
void gcd(LL a,LL b,LL &t,LL &x,LL &y)
{
    if(!b)
    {
        t=a;    //边界:gcd(a,0)=1*a+0*0=a
        x=1;
        y=0;
    }
    else
    {
        gcd(b,a%b,t,y,x);
        y-=x*(a/b);
    }
}
int main()
{
    cin>>a>>b;
    gcd(a,b,t,x,y);
    if(t!=1)cout<<"No answer"<<endl;
    else cout<<(x%b+b)%b<<endl;
    return 0;
}

第二种类似做法:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL extend_gcd(LL a,LL b,LL &x,LL &y)
{
    LL ret,temp;//ax+by=gcd(a,b);
    if(!b)//判断结束语句;
    {
        x=1;
        y=0;
        return a;
    }
    ret=extend_gcd(b,a%b,x,y);
    temp=x;
    x=y;
    y=temp-a/b*y;
    return ret;
}
int main()
{
    LL a,b,x,y,z;
    cin>>a>>b;
    z=extend_gcd(a,b,x,y);
    //cout<<z<<endl;
    b=b/z;
    cout<<(x%b+b)%b;
    //cout<<x<<" "<<y;
}

对于ax+by=c有整数解的充要条件为c%gcd(a,b)=0;

代码:

#include<iostream>
#include<algorithm>
using namespace std;
int extend_gcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int d=extend_gcd(b,a%b,x,y);
    int temp=x;
    x=y;
    y=temp-a/b*y;
    return d;
}
//扩展欧几里得求ax+by=c;
bool ok(int a,int b,int c,int &x,int &y)
{
    int d=extend_gcd(a,b,x,y);
    if(c%d==1)return 0;
    int k=c/d;
    x*=k;
    y*=k;
    return 1;
}
int main()
{
    int a,b,c,x,y;
    cin>>a>>b>>c;
    if(ok(a,b,c,x,y))
    {
        cout<<"ok"<<endl;
        cout<<x<<" "<<y;
    }

}
求最小正x

#include<iostream>
#include<algorithm>
using namespace std;
int f;
int extend_gcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int d=extend_gcd(b,a%b,x,y);
    int temp=x;
    x=y;
    y=temp-a/b*y;
    return d;
}
//扩展欧几里得求ax+by=c;
bool ok(int a,int b,int c,int &x,int &y)
{
    f=extend_gcd(a,b,x,y);
    if(c%f==1)return 0;//判断条件;
    int k=c/f;
    x*=k;
    y*=k;
    return 1;
}
int main()
{
    int a,b,c,x,y;
    cin>>a>>b>>c;
    if(ok(a,b,c,x,y))
    {
        cout<<"ok"<<endl;
        cout<<x<<" "<<y<<endl;
    }
    b/=f;
    cout<<(x%b+b)%b;
}
 

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/81332509