扩展欧几里得

用处:求\(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
posted @ 2020-07-25 13:08  zjjws  阅读(107)  评论(0)    收藏  举报