原题链接
P1082
题目类型:
普
及
+
/
提
高
{\color{lightgreen} 普及+/提高}
普及+/提高
AC记录:Accepted
题目大意
求关于 x x x的同余方程 a x ≡ 1 ( m o d b ) ax\equiv 1(\bmod\ b) ax≡1(mod b)的最小正整数解。
输入格式
一行,包含两个正整数 a , b a,b a,b,用一个空格隔开。
输出格式
一个正整数 x 0 x_0 x0,即最小正整数解。输入数据保证一定有解。
S a m p l e \mathbf{Sample} Sample I n p u t \mathbf{Input} Input
3 10
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
7
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
无
数据范围
对于
40
%
40\%
40%的数据,
2
≤
b
≤
1
,
000
2≤b≤1,000
2≤b≤1,000。
对于
60
%
60\%
60%的数据,
2
≤
b
≤
50
,
000
,
000
2≤b≤50,000,000
2≤b≤50,000,000。
对于
100
%
100\%
100%的数据,
2
≤
a
,
b
≤
2
,
000
,
000
,
000
2\le a,b\le 2,000,000,000
2≤a,b≤2,000,000,000。
解题思路
这题可以用拓展欧几里得算法(下面简称拓欧)来解决。
而拓欧解的方程是这样的: a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b),与我们的题目有很大的区别。所以我们要把题目中的同余方程变成这个样子: a x + b y = 1 ax+by=1 ax+by=1。其中的 y y y为辅助解,没什么用。又由于题目中说了:输入数据保证一定有解,所以又可以得知: gcd ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1。
解完方程以后,还有一个需要注意的点,就是题目要求的是最小正整数解,那么我们解出一个解后,如何找出其他的解呢?
答案是:设方程的一个解为
x
x
x,则
x
+
k
b
x+kb
x+kb都是方程的解。
如果把
x
+
k
b
x+kb
x+kb代入原方程,可以得到
a
(
x
+
k
b
)
≡
1
(
m
o
d
b
)
a(x+kb)\equiv 1(\bmod\ b)
a(x+kb)≡1(mod b),去括号后变成
a
x
+
k
a
b
≡
1
(
m
o
d
b
)
ax+kab\equiv 1(\bmod\ b)
ax+kab≡1(mod b)。由于
k
a
b
kab
kab一定是
b
b
b的倍数,所以方程又变成了
a
x
≡
1
(
m
o
d
b
)
ax\equiv 1(\bmod\ b)
ax≡1(mod b),即为原方程。所以求最小正整数解就相当于把
x
x
x变成
(
(
x
+
m
o
d
b
)
+
b
)
m
o
d
b
((x+\bmod\ b)+b)\bmod\ b
((x+mod b)+b)mod b。
注意:由于解出来的
x
x
x有可能是负数,所以上式在
m
o
d
b
\bmod\ b
mod b之后还要再加上一个
b
b
b再取模。
最后,祝大家早日
上代码
#include<iostream>
using namespace std;
int x,y;
int exgcd(int a,int b)
{
if(b==0)
{
x=1,y=0;
return a;
}
int temp=exgcd(b,a%b);
int tx=x;
x=y;
y=tx-a/b*y;
return temp;
}
int main()
{
int a,b;
cin>>a>>b;
exgcd(a,b);
// cout<<x<<" "<<y<<endl;
x=((x%b)+b)%b;
cout<<x<<endl;
return 0;
}
完美切题 ∼ \sim ∼