The equation SGU - 106

原题链接

考察:扩展gcd

思路:

        套exgcd模板但是答案没有那么简单!!!

坑点:

  1. 存在!a||!b的情况,此时答案是系数为0的变量的范围.但是if !a&&!b 此时只有!c才存在答案.
  2. 此时a&&b, 我们可以求出x,y的某一个解.如果直接while(x+=b/d)统计会TLE.因此必须转换为其他解法.
  3. 此题不好求靠近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.
  4. 但是!我们将b/gcd(a,b)或者a/gcd(a,b)转换到不等式另一边的时候,要考虑负数变号.
  5. 并且左边界是上取整(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 }

 

posted @ 2021-03-23 01:02  acmloser  阅读(11)  评论(0编辑  收藏  举报