方程的解(exgcd模板)
Posted toot-wjh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方程的解(exgcd模板)相关的知识,希望对你有一定的参考价值。
题面在考试反思中。
题解:
这题其实只是个板子题,但考试时忘记了,又不会推导,于是凉凉。。。
借这道题回顾一下$ exgcd $的各种特判:
我习惯将方程$ ax+by=c $看成一次函数$ y=-\fracabx+\fraccb $
而在此之前我们要特判b是否为0,再根据一次函数的性质来判断。
$ a,b,c $都为0时,无数组解。
$ a,b $为0且$ c $不为0时,无解
$ b=0 $时,若$ a*c<0 $,无正整数解。
若$ c\%a=0 $,无数组解。
$b$不为0时,若$ a=0 $时,同$b$。
若$ a*b<0 $时,判断是否有无穷解,若否则为无正整数解。
若$ a*b>0 $时,分三种情况:
$ c=0 $时,无正整数解。
$ c*b<0 $时,无正整数解。
$ c*b>0 $时,需我们进行求解。
而求解时我们不需枚举每个解,只需算出最大解及最小解即可,
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 #include<algorithm> 7 using namespace std; 8 #define R register 9 #define ll long long 10 inline ll read() 11 ll aa=0;R int bb=1;char cc=getchar(); 12 while(cc<‘0‘||cc>‘9‘) 13 if(cc==‘-‘)bb=-1;cc=getchar(); 14 while(cc>=‘0‘&&cc<=‘9‘) 15 aa=(aa<<1)+(aa<<3)+(cc^48);cc=getchar(); 16 return aa*bb; 17 18 const int lim=65535; 19 ll exgcd(ll a,ll b,ll &x,ll &y) 20 21 if(!b)x=1;y=0;return a; 22 ll d=exgcd(b,a%b,x,y); 23 ll z=x;x=y;y=z-y*(a/b); 24 return d; 25 26 ll T,a,b,c;//6 27 inline bool solve(ll &x,ll &y) 28 29 ll gcd=exgcd(a,b,x,y); 30 if(c%gcd)return 0; 31 ll t=c/gcd; 32 x*=t;y*=t; 33 if(a*x+b*y!=c)return 0; 34 t=b/gcd; 35 if(t<0)t=-t; 36 while(x<0)x+=t; 37 x%=t; 38 if(!x)x+=t; 39 a/=gcd;b/=gcd;c/=gcd;//4 40 return 1; 41 42 inline bool work() 43 44 if((!a)&&(!b)&&(!c)) 45 puts("ZenMeZheMeDuo"); 46 return 0; 47 48 if(a==0&&b==0) 49 puts("0");return 0; 50 51 if(!b) 52 if(c*a<0) puts("0"); 53 else if(c%a==0) puts("ZenMeZheMeDuo");//5 54 else puts("0"); 55 return 0; 56 57 if(!a) 58 if(b*c<0) puts("0"); 59 else if(c%b==0) puts("ZenMeZheMeDuo"); 60 else puts("0"); 61 return 0; 62 63 if(a*b>0&&(b*c<0||!c)) puts("0");return 0; 64 if(a<0&&b<0)a=-a;b=-b;c=-c; 65 return 1; 66 67 int main() 68 69 T=read(); 70 while(T--) 71 a=read();b=read();c=read(); 72 if(!work())continue;//特判 73 ll xi,yi,yj,ans=0; 74 if(!solve(xi,yi)) 75 puts("0");continue; 76 77 else 78 if(a*b<0)//2 79 puts("ZenMeZheMeDuo"); 80 continue; 81 82 if(a+b==c) puts("1");continue; 83 if(a==b&&a==1) 84 c-=1; 85 if(c>lim) puts("ZenMeZheMeDuo"); 86 else printf("%lld\n",c); 87 continue; 88 89 yi=(c-a*xi)/b; 90 yj=yi%a; 91 if(yj<=0)yj+=a; 92 if(yj>yi) puts("0");continue; 93 ans=(yi-yj)/a+1;//3 94 if(ans>lim)puts("ZenMeZheMeDuo"); 95 else printf("%lld\n",ans); 96 97 98 return 0; 99
以上是关于方程的解(exgcd模板)的主要内容,如果未能解决你的问题,请参考以下文章