题面描述
已知a,b,m,求x的最小正整数解,使得ax=b(mod m)
【输入格式】
一行三个整数 a,b,m。 1 ≤ a,b,m ≤ 10^9
【输出格式】
一行一个整数x,无解输出"no solution!"
【样例输入】
2 5 7
【样例输出】
6
思路
从题目的
a
x
=
b
(
m
o
d
m
)
ax=b(mod~m)
ax=b(mod m),可以转化为
a
x
+
m
y
=
b
ax+my=b
ax+my=b;
借助exgcd模版 ,我们可以直接套公式,得出特殊解x;
怎么转化为最小整数解x呢,设
d
=
g
c
d
(
a
,
m
)
d=gcd(a,m)
d=gcd(a,m);
x
=
(
x
m
o
d
(
m
/
d
)
+
m
/
d
)
)
m
o
d
(
m
/
d
)
x=(x ~mod~ (m/d)+m/d))~mod~(m/d)
x=(x mod (m/d)+m/d)) mod (m/d);
证明如下:
对于
a
∗
x
0
+
m
∗
y
0
=
b
a*x_0+m*y_0=b
a∗x0+m∗y0=b,都有
a
∗
(
x
0
+
m
/
d
∗
t
)
+
m
∗
(
y
0
−
a
/
d
∗
t
)
=
b
a*(x_0+m/d*t)+m*(y_0-a/d*t)=b
a∗(x0+m/d∗t)+m∗(y0−a/d∗t)=b.
t
t
t是变化次数
观察一下这个柿子,
(
x
0
+
m
/
d
∗
t
)
(x_0+m/d*t)
(x0+m/d∗t),
(
y
0
−
a
/
d
∗
t
)
(y_0-a/d*t)
(y0−a/d∗t),需要满足
m
/
d
,
a
/
d
m/d,a/d
m/d,a/d均为正整数,且要求
m
/
d
m/d
m/d最小,因此,
d
d
d应满足是
m
,
a
m,a
m,a的公约数,且要最大,就为最大公约数
g
c
d
(
a
,
m
)
gcd(a,m)
gcd(a,m)。
∴
\therefore
∴ 当
t
=
1
t=1
t=1,
m
/
d
m/d
m/d是
x
0
x_0
x0 每次增加量的最小幅度
x
=
(
x
m
o
d
(
m
/
d
)
+
(
m
/
d
)
)
m
o
d
(
m
/
d
)
x=(x~mod~(m/d)+(m/d))~mod~(m/d)
x=(x mod (m/d)+(m/d)) mod (m/d)即为最小正整数解
证毕。
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;y=0;
return a;
}
else
{
ll tx,ty;
ll d=exgcd(b,a%b,tx,ty);
x=ty;y=tx-(a/b)*ty;
return d;
}
}
int main()
{
ll a,b,m,x,y;scanf("%lld%lld%lld",&a,&b,&m);
ll d=exgcd(a,m,x,y);
if(b%d){puts("no solution!");return 0;}
x=x*b/d;
y=(b-a*x)/m;
x=(x%(m/d)+(m/d))%(m/d);
printf("%lld\n",x);
return 0;
}