过一段时间不用拓展欧几里得就把代码忘了,这是没有深入理解的恶果啊。写下一文,回忆回忆基础而重要的拓展欧几里得
拓展欧几里得函数 ex_gcd() 可以用于求解逆元,不定方程,同余式(随便也能把模与被模数的最大公约数求出来)。
贴上代码:
void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){ if(b==0){ d=a; x=1; y=0; return ; } ex_gcd(b,a%b,d,x,y); LL t=x; x=y; y=t-a/b*y; }
void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){ cout<<d<<" "<<a<<" "<<b<<endl; if(b==0){ d=a; x=1; y=0; return ; } ex_gcd(b,a%b,d,x,y); LL temp=x; x=y; y=temp-a/b*y; cout<<d<<" "<<x<<" "<<y<<" "<<a<<" "<<b<<endl; } int main() { LL d,x,y; ex_gcd(225,21,d,x,y); return 0; }
#include <iostream> #include <cstdio> using namespace std; typedef long long LL; void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){ if(b==0){ d=a; x=1; y=0; return ; } ex_gcd(b,a%b,d,x,y); LL t=x; x=y; y=t-a/b*y; } LL abs(LL a){ return a<0?-a:a; } int main() { //freopen("cin.txt","r",stdin); LL a,b,c; while(~scanf("%lld%lld%lld",&a,&b,&c)){ if(a==0&&b==0&&c==0) break; bool sp=0; if(a>b){ sp=1; a=a^b; b=a^b; a=a^b; } LL d,x0,y0; ex_gcd(a,b,d,x0,y0); x0=x0*(c/d); y0=y0*(c/d); LL t=x0*d/b,Min=0x3f3f3f3f,Min2=0x3f3f3f3f; LL ans1,ans2; for(int i=t-2;i<t+2;i++){ LL get=abs(x0-b/d*i)+abs(y0+a/d*i); if(Min>get){ ans1=x0-b/d*i; ans2=y0+a/d*i; Min=get; Min2=a*ans1+b*ans2; } else if(Min==get){ LL all=abs(a*(x0-b/d*i))+abs(b*(y0+a/d*i)); if(all<Min2){ Min2=all; ans1=x0-b/d*i; ans2=y0+a/d*i; } } } if(sp) { ans1=ans1^ans2; ans2=ans1^ans2; ans1=ans1^ans2; } printf("%lld %lld\n",abs(ans1),abs(ans2)); } return 0; }
#include <iostream> #include <cmath> #include <cstdio> using namespace std; typedef long long LL; void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){ if(b==0){ d=a; x=1; y=0; return ; } ex_gcd(b,a%b,d,x,y); LL temp=x; x=y; y=temp-a/b*y; } int main() { //freopen("cin.txt","r",stdin); LL a,b,c; LL x1,x2,y1,y2; while(~scanf("%lld%lld%lld",&a,&b,&c)){ scanf("%lld%lld",&x1,&x2); scanf("%lld%lld",&y1,&y2); if(b==0){ if(a!=0){ if(c%a==0&&(-c/a)<=x2&&(-c/a)>=x1) { //one x but name y printf("%lld\n",y2-y1+1); } else puts("0"); } else { LL ans=(x2-x1+1LL)*(y2-y1+1); if(c==0)printf("%lld\n",ans); else puts("0"); } } else if(a==0){ if(b!=0){ if(c%b==0&&(-c/b)<=y2&&(-c/b)>=y1) { //one y but many x printf("%lld\n",x2-x1+1); } else puts("0"); } else { LL ans=(y2-y1+1LL)*(x2-x1+1); if(c==0)printf("%lld\n",ans); else puts("0"); } } else { c=-c; if(c<0){ c=-c; a=-a; b=-b; } if(a<0) { a=-a; LL t=x1; x1=-x2; x2=-t; } if(b<0) { b=-b; LL t=y1; y1=-y2; y2=-t; } LL d,x,y; ex_gcd(a,b,d,x,y); if(c%d){ puts("0"); continue; } a/=d; b/=d; c/=d; x=x*c; y=y*c; LL l=max(ceil((y-y2)*1.0/a),ceil((x1-x)*1.0/b)); LL r=min(floor((y-y1)*1.0/a),floor((x2-x)*1.0/b)); if(r<l) puts("0"); else printf("%lld\n",r-l+1); } } return 0; }