The equation SGU - 106
考察:扩展gcd
思路:
套exgcd模板但是答案没有那么简单!!!
坑点:
- 存在!a||!b的情况,此时答案是系数为0的变量的范围.但是if !a&&!b 此时只有!c才存在答案.
- 此时a&&b, 我们可以求出x,y的某一个解.如果直接while(x+=b/d)统计会TLE.因此必须转换为其他解法.
- 此题不好求靠近l1的x解或者靠近l2的y解.但是 x = x0+k*b/gcd(a,b) y = y0-a/gcd(a,b)*k 将考虑两个变量范围问题转化为考虑一个变量即k的范围.利用l1<=x <=r1&&l2<=y<=r2.可以确定k的取值范围.答案是r-l+1.
- 但是!我们将b/gcd(a,b)或者a/gcd(a,b)转换到不等式另一边的时候,要考虑负数变号.
- 并且左边界是上取整(eg:136.33->137,-98.07->-98),右边界是下取整.此时可以考虑用ceil和floor两个函数.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 typedef long long LL; 7 LL a,b,c,l1,r1,l2,r2,x,y,ans; 8 LL exgcd(LL a,LL b,LL& x,LL& y) 9 { 10 if(!b) 11 { 12 x = 1,y = 0; 13 return a; 14 } 15 LL d = exgcd(b,a%b,y,x); 16 y-=a/b*x; 17 return d; 18 } 19 void solve() 20 { 21 LL d = exgcd(a,b,x,y); 22 if(c%d!=0) {puts("0");return;} 23 x*=(-c)/d,y*=(-c)/d; 24 LL s = b/d,l,r,temp; 25 if(s<0) 26 { 27 l = ceil(1.0*(r1-x)/s); 28 r = floor(1.0*(l1-x)/s); 29 }else{ 30 l = ceil(1.0*(l1-x)/s); 31 r = floor(1.0*(r1-x)/s);//l是上取整 32 } 33 s = a/d; 34 if(s<0) 35 {//166.333 36 temp = ceil(1.0*(y-l2)/s); 37 l = max(temp,l); 38 r = min((LL)floor(1.0*(y-r2)/s),r); 39 }else{ 40 temp = ceil(1.0*(y-r2)/s); 41 l = max(temp,l); 42 r = min((LL)floor(1.0*(y-l2)/s),r); 43 } 44 ans = max(r-l+1,0ll); 45 } 46 int main() 47 { 48 scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&l1,&r1,&l2,&r2); 49 if(!a&&!b&&!c) ans = (r1-l1+1)*(r2-l2+1); 50 else if(!a&&!b&&c) ans = 0; 51 else if(!a&&c%b==0) ans = r2-l2+1; 52 else if(!b&&c%a==0) ans = r1-l1+1; 53 else if(a&&b) solve(); 54 printf("%lld\n",ans); 55 return 0; 56 }