扩展欧几里得
用处:求\(ax\equiv c(\% b)\)的解
实现:
1.推导,化为\(ax+by=c\)的形式
2.判断方程是否有解,如果满足\(gcd(a,b)|c\),则有解
3.将方程左右两边同除以\(gcd(a,b)\)化为等价方程式
4.扩欧求出其中一个解\(x_1\)
5.利用公式推导得出\(min_x=x_1\% (b/gcd(a,b))\)
据我同学说直接\(\%\)原来的\(b\)会出问题,我在这里小证一下
我同学一开始的想法
\[ax+by=c-->a(x+k*b)+b(y-k*a)=c,k\epsilon N
\]
所以我们求出来的\(x\)可以通过\(\%b\)得到最小值
但是他WA了
我们设由这个转换得到的x的取值范围为 \(P_1\)
设 \(g=gcd(a,b),a=g*a^{'},b=g*b^{'},c=g*c^{'}\)
上述中第三步操作后的方程式就可以表示为
\[a^{'}x+b^{'}y=c^{'}-->a^{'}(x+k*b^{'})+b^{'}(y-k*a^{'})=c^{'},k\epsilon N
\]
设此时得到的 \(x\) 的取值范围为 \(P_2\)
很明显因为模数 \(b^{'}|b\)
对于我们求出来相同的\(x\)的其中一个值
我们得到的定义域 \(P_1\subseteq P_2\)
\(\% b^{'}\) 能得到的答案会更优
注:用扩欧求逆元的方程式\(ax+by=1\),有解的条件为\(gcd(a,b)=1\),即\(a,b\)互质
就放一个求逆元的代码吧
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL x,y;
inline void dfs(LL a,LL b)
{
if(b==0)x=1,y=0;
else
{
dfs(b,a%b);
LL l_x=x,l_y=y;
x=l_y;y=l_x-(a/b)*l_y;
}
return;
}
LL rin()
{
LL s=0;
char c=getchar();
bool bj=0;
for(;(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')c=getchar(),bj=true;
for(;c>='0'&&c<='9';c=getchar())s=(s<<1)+(s<<3)+(c^'0');
if(bj)return -s;
return s;
}
int main()
{
//ax+by=1
int i,j;
LL a,b;
a=rin();b=rin();
dfs(a,b);
printf("%lld",(x%b+b)%b);
return 0;
}
//cd 下载
//g++ a+b.cpp -o a+b.exe
//./a+b.exe
$$\texttt{Dirty Deeds Done Dirt Cheap}$$