求关于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;
}