题面在考试反思中。
题解:
这题其实只是个板子题,但考试时忘记了,又不会推导,于是凉凉。。。
借这道题回顾一下$ exgcd $的各种特判:
我习惯将方程$ ax+by=c $看成一次函数$ y=-\frac{a}{b}x+\frac{c}{b} $
而在此之前我们要特判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 }
龟速1022ms代码
原文地址:https://www.cnblogs.com/toot-wjh/p/11235593.html
时间: 2024-11-01 22:27:49