扩欧复习课
很多题解对我来说啃起来有难度,我在这里写一下自己的理解吧。
\(Part\;1\).
欧几里得算法。
一行了事,没大问题。
\(Code\):
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}
相关定理:
挺有用的。
\(Part\;2\).
裴蜀定理。
不定方程
有整数解的充分条件是:
很简单,设 \(a=k_1\gcd(a,b),b=k_2\gcd(a,b)\),
左边 \(=(k_1x+k_2y)\gcd(a,b)=\) 右边,存在解。
得证。
例题:P4549 【模板】裴蜀定理
裴蜀定理对多元不定方程仍成立。
\(Part\;3\).
不定方程。
考虑有解的不定方程:
的一组解。
运用裴蜀定理,两边同时除以 \(\gcd(a,b)\),假设为:
同时除以 \(c'\),得:
令 \(x'=\dfrac{x}{c'},y'=b'\dfrac{y}{c'}\),方程化为:
可以跑拓欧了。
等一下,拓欧咋跑?
\(Part\;4\).
拓展欧几里得。
求解方程:
或是
找个 \(y\) 值,使得 \(ax=by+1\),显然 \(ax-by=1\) ,这里令 \(y\leqslant0\),得:
就是上式了。
显然 \(a,b\) 互质。
我们令 \(a_1=b,b_1=(a\bmod b)\),得一新方程:
我们的任务就是找这两个方程的解了。
由取模定义:
\(a\bmod b=a-b\left\lfloor\dfrac{a}{b}\right\rfloor\),可得:
整理一下可知:
那么原方程的解为:
那么 \(x_1,y_1\) 怎么求呢?
发现可以递归,最后会出现:
如果是求逆元,记得处理负数。
下面放上板子题代码:
\(Code\):
void exgcd(ll a,ll b)
{
if(b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b);
ll t=x;
x=y;
y=t-a/b*y;
}
int main()
{
ll a,b;
cin>>a>>b;
exgcd(a,b);
x=(x+b)%b;
cout<<x;
return 0;
}
\(Part\;5\).
不定方程(进阶)。
上面说过一些,不过这里是找通解。
有个结论:
证明很费解:
发现只需证 \(ax_t+by_t=1\) 即可。
若成立
左边 \(=a(x_0+b't)+b(y_0-a't)=ax_0+by_0+ab't-a'bt=1+\dfrac{abt}{\gcd(a,b)}-\dfrac{abt}{\gcd(a,b)}=1=\) 右边。
得证。
\(Part\;6\).
关于 \(x,y\) 的最小(大)整数解。
对于 \(x\),就是个碾转相除嘛,求出的特解 \(x\) 一定是:
对 \(b'\) 取模即得 \(x_{min}\),
其实是满足:
的。
那么解的数量:
(加上两边)
这些同理于 \(y\)。
就这些了。
\(Code\):
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long x,y;
long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
void exgcd(long long a,long long b)
{
if(b==0)
{
x=1,y=0;
return;
}
exgcd(b,a%b);
long long t=x;
x=y;
y=t-a/b*y;
}
long long t,a,b,c,g,minx,miny,maxx,maxy,num;
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&a,&b,&c);
g=gcd(a,b);
if(c%g)
{
printf("-1\n");
continue;
}
a/=g,b/=g,c/=g;
exgcd(a,b);
x*=c,y*=c;
minx=(x%b+b)%b;
if(!minx) minx+=b;
miny=(y%a+a)%a;
if(!miny) miny+=a;
maxx=(c-(b*miny))/a;
maxy=(c-(a*minx))/b;
num=(maxx-minx)/b+1;
if(num) printf("%lld %lld %lld %lld %lld\n",num,minx,miny,maxx,maxy);
else printf("%lld %lld\n",minx,miny);
}
return 0;
}
乱用 long long
......