思路:用拓展欧几里得算法可以得出原方程的一个解。然后就可以根据这个解判断在所给的区间里有几个解。
由ax+by+c = 0有ax+by = -c,两边取模b得到
ax+by ≡ -c (mod b) 推出 ax ≡ -c (mod b)
模线性方程有解当且仅当gcd(a,b) | -c,有解的情况下方程对模-c有d个不同的解,d=gcd(a,b)
根据拓展欧几里得算法可以算出x0, y0使得d = a*x0+b*y0
则x = x0*(-c/d), y = y0*(-c/d)为原方程ax+by+c=0的一个解
则方程的所有解为x = x0*(-c/d) + i*(b/d), y = y0*(-c/d) - i*(a/d)
计算所有的i使得解在所给区间内的个数即可。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #define ll long long int 9 #define mod 1000000007 10 #define ceils(a,b) ceil(double(a)/double(b)) //向上取整 11 #define floors(a,b) floor(double(a)/double(b)) //向下取整 12 using namespace std; 13 ll extend(ll a,ll b,ll &x,ll &y) 14 { 15 if(b==0){ 16 x=1; 17 y=0; 18 return a; 19 } 20 else{ 21 ll t=extend(b,a%b,x,y); 22 ll c=x; 23 x=y; 24 y=c-a/b*y; 25 return t; 26 } 27 } 28 int main(){ 29 ll a,b,c,x1,x2,y1,y2; 30 ll x,y,k1,k2,k3,k4,d,g; 31 cin>>a>>b>>c>>x1>>x2>>y1>>y2; 32 if(!(x1<=x2&&y1<=y2)) cout<<0<<endl; 33 else if(a==0&&b==0) cout<<(c==0)*(x2-x1+1)*(y2-y1+1)<<endl; 34 else if(a==0){ 35 y=-c/b; 36 cout<<((b*y+c==0)&&(y1<=y&&y<=y2))*(x2-x1+1)<<endl; 37 } 38 else if(b==0){ 39 x=-c/a; 40 cout<<((a*x+c==0)&&(x1<=x&&x<=x2))*(y2-y1+1)<<endl; 41 } 42 else{ 43 g=extend(a,b,x,y); 44 if(c%g==0){ 45 a/=g;b/=g;c/=g; 46 x*=-c;y*=-c; 47 if(b>0){ 48 k1=ceils(x1-x,b); 49 k2=floors(x2-x,b); 50 } 51 else{ 52 k1=ceils(x2-x,b); 53 k2=floors(x1-x,b); 54 } 55 if(a<0){ 56 k3=ceils(y-y1,a); 57 k4=floors(y-y2,a); 58 } 59 else{ 60 k3=ceils(y-y2,a); 61 k4=floors(y-y1,a); 62 } 63 ll mi=min(k2,k4); 64 ll ma=max(k1,k3); 65 if(mi>=ma) cout<<mi-ma+1<<endl; 66 else cout<<0<<endl; 67 } 68 else cout<<0<<endl; 69 } 70 return 0; 71 }