【数论】裴蜀定理+拓展欧几里得算法
Part 1:裴蜀定理
一、定理内容:
对于方程 ax+by=d,若有解x∈Z*,y∈Z*,则gcd(a,b)|d
二、很不严谨的证明:
设s=gcd(a,b),显然s|a,s|b
x∈Z*,y∈Z*,因此s|ax,s|by
要使ax+by=d成立,d必然是s的倍数
得证
三、例题:P4549 【模板】裴蜀定理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
(1)思路:上文所述的裴蜀定理只解决了两个未知数的情况,实际上可以拓展到多个未知数
式子形如 a1x1+a2x2+a3x3+...+anxn=d,若x1到xn均为整数,则gcd(a1,a2,...,an)|d,证明方式相同
(2)solution:
#include<bits/stdc++.h> using namespace std; int n; inline int GCD(int x,int y)//欧几里得算法求gcd(a,b)
{return x%y?GCD(y,x%y):y;} int main() { scanf("%d",&n); int ans=0,tmp; for(int i=1;i<=n;i++) { scanf("%d",&tmp); if(tmp<0) tmp=-tmp;//gcd(a,b)=gcd(a,-b),为避免出错,都调为正 if(!tmp) continue;//a%0是错误的,排除 ans=GCD(ans,tmp);//求当前数字与前面所有数的gcd的gcd
//特别的,当ans=0时GCD(0,tmp)=tmp } printf("%d",ans); }
Part 2:拓展欧几里得算法
一、算法原理:
对于每对整数a,b有且仅有一组整数x,y满足 ax+by=gcd(a,b),且gcd(a,b)是满足此关系的最小值
可以看出,拓展欧几里得就是裴蜀定理的一种应用,欧几里得算法就可以求出x,y
二、递推式证明:
先看gcd(a,b)的计算过程
a | b | 余数r | 商q |
a | b | r1=a%b | q1=a÷b |
b | r1 | r2=b%r1 | q2=b÷r1 |
... | ... | ... | ... |
rn-2 | rn-1 | rn=rn-2+rn-1 | qn=rn-2÷rn-1 |
rn-1 | rn | rn+1=rn-1%rn | qn+1=rn-1÷rn |
直到出现rn-1%rn=0的情况,找到了最大公约数,返回rn
由ri÷ri+1=qi······ri+2得ri=ri÷ri+1×rr+i+ri+2 ①
式子有点奇怪,但先不要化简
因为ax+by=d,所以在gcd(a,b)过程中,任意rixi+ri+1yi=gcd(a,b)是成立的,因此我们可以得到
rixi+ri+1yi=gcd(a,b) ②
ri+1xi+1+ri+2yi+1=gcd(a,b) ③
将式①分别代入②③,并将②③合并可以得到
(ri÷ri+1·ri+1+ri+2)xi+ri+1yi=ri+1xi+1+ri+2yi+1
然后进行变形
ri÷ri+1·ri+1xi+ri+2xi+ri+1yi=ri+1xi+1+ri+2yi+1
(ri÷ri+1·xi+yi)ri+1+ri+2xi=ri+1xi+1+ri+2yi+1
由系数相等的性质可得
yi=xi+1+xi·ri÷ri+1
xi=yi+1
至此,我们就得到了xi与xi+1之间的递推关系
三、递归边界:
找到了递推式,我们需要一个边界
在rn%rn+1=0时,gcd(a,b)=rn+1,显然,此时方程
rnx+rn+1y=gcd(a,b)
的解为x=0,y=1
这样,我们就可以利用最后一组解计算出原来x,y的值
四、代码模板:
#include<bits/stdc++.h> #define ll long long//代码千万条,long long第一条 using namespace std; ll exgcd(ll a,ll b,ll &x,ll &y) { if (b==0){x=1,y=0;return a;}//到达边界,回溯 ll d=exgcd(b,a%b,x,y),tmp=x;//tmp中存的是xi+1,ans中存的是gcd(a,b) x=y,y=tmp-a/b*y;//递推关系式 return d; } int main() { ll a,b,x,y; scanf("%lld%lld",&a,&b); printf("%lld",exgcd(a,b,x,y));//输出gcd(a,b) printf(" %lld %lld\n",x,y);//输出x,y }
五、例题:
已知a,b求解ax+by=gcd(a,b)的一组整数解,使得|x|+|y|最小
输入格式:输入为T组数据,第一行有一个正整数T,接下来T行每行两个正整数a,b
输出格式:对于每组输出,输出三个整数d,x,y
样例输入:
4 6 6 8 12 11 17 2 8
样例输出:
6 0 1 4 -1 1 1 -3 2 2 1 0
看到题目第一眼我愣了一下,如何对解加限制?
但是拿这个题出来只是为了强调一点ax+by=gcd(a,b)有且只有一组解!!!
然后套模板就可以了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现