SGU 106 The euqation

坑点:在处理闭区间边界时,涉及到取ceil和floor的问题,当a>0,b>0时,a/b取floor,可以用(a-1)/b+1取ceil,而a<0,b>0时,a/b取ceil,可以用(a+1)/b-1取floor,a=0特殊考虑,直接a/b就行。 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
void ExEuclid(LL a,LL b,LL &x,LL &y,LL &d)
{
    if(b==0)
    {
        d=a,x=1,y=0;
        return ;
    }
    else
    {
        ExEuclid(b,a%b,x,y,d);
        LL t=x;
        x=y;
        y=t-a/b*y;
        return ;
    }
}
LL Work(LL a,LL b,LL c,LL x1,LL x2,LL y1,LL y2)
{
    LL l1=x1,r1=x2,l2=y1,r2=y2;
    if(a==0&&b==0)
    {
        if(c!=0)
            return 0;
        return (x2-x1+1)*(y2-y1+1);
    }
    if(a==0)
    {
        if(c%b!=0)
            return 0;
        if((-c)/b<=y2&&(-c)/b>=y1)
            return (x2-x1+1);
        return 0;
    }
    if(b==0)
    {
        if(c%a!=0)
            return 0;
        if((-c)/a<=x2&&(-c)/a>=x1)
            return (y2-y1+1);
        return 0;
    }
    if(a<0)
    {
        a=-a;
        swap(l1,r1);
        l1=-l1,r1=-r1;
    }
    if(b<0)
    {
        swap(l2,r2);
        l2=-l2,r2=-r2;
        b=-b;
    }
    LL x0,y0,d;
    ExEuclid(a,b,x0,y0,d);
    if(c%d!=0)
        return 0;
    c=(-c)/d,a/=d,b/=d;
    l1-=c*x0,r1-=c*x0;
    if(l1<=0)     //注意这里边界的处理,l1/=b使得绝对值减小,当l1为正数时起到floor作用,当l1为负数时起到ceil作用
        l1/=b;
    else
        l1=(l1-1)/b+1;    //只有当l1>=1时才能取到ceil作用
    if(r1<0)
    {
        r1=(r1+1)/b-1;
    }
    else
        r1/=b;
    l2-=c*y0,r2-=c*y0;
    swap(l2,r2);
    l2=-l2,r2=-r2;
    if(l2<=0)
        l2/=a;
    else
        l2=(l2-1)/a+1;
    if(r2<0)
    {
        r2=(r2+1)/a-1;
    }
    else
        r2/=a;
    LL l=l1,r=r1;
    if(l2>l1)
        l=l2;
    if(r2<r1)
        r=r2;
    if(l<=r)
        return r-l+1;
    else
        return 0;
}
int main()
{
    LL a,b,c,x1,y1,x2,y2;
    while(scanf("%lld %lld %lld %lld %lld %lld %lld",&a,&b,&c,&x1,&x2,&y1,&y2)!=EOF)
    {
        if(x1>x2||y1>y2)
            printf("0\n");
        else
            printf("%lld\n",Work(a,b,c,x1,x2,y1,y2));
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值