【扩展欧几里得+解不等式】sgu106The equation

题目链接
题目大意:对于一个不定方程 ax+by+c=0 ,其中 x[x1,x2] y[y1,y2] 。求有多少组解。
数据范围:每一个数的绝对值不超过 108

一道裸的扩展欧几里得。
首先将方程变式为 ax+by=c ,即 c=c
假设 a,b,c 都是正数。
若求得一组解 x,y ,那么 x=x+kb/d,y=yka/d 则是另一组解。
要判断解的个数,就是计算有多少个 k

对于x, (x1x)/(b/d)<=k<=(x2x)/(a/d)
对于y, (yy2)/(a/d)<=k<=(yy1)/(a/d)
然后再合并一下。

那么负数肿么办?
变为正数就行了。
取相反数,取值范围也取相反数。
在这里将负数变为正数是有必要的,若是负数, k 的取值范围就要取反。如果不将负数变为正数,就进行分类讨论。

在解不等式时,注意上取整和下取整的问题,最好用 floor ceil 函数。(蒟蒻就是在这里wa了无数遍)

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;

void gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(!b)
        d=a ,x=1 ,y=0 ;
    else
    {
        gcd(b,a%b,d,y,x);
        y-=a/b*x;
    }
}

LL a ,b ,c ,x1 ,x2 ,yy1 ,yy2 ;
LL d ,x ,y ;

int main()
{
    cin>>a>>b>>c>>x1>>x2>>yy1>>yy2;
    c=-c;
    if(c<0)
        c=-c ,a=-a ,b=-b ;
    if(a<0)
        a=-a ,swap(x1,x2) ,x1=-x1 ,x2=-x2;
    if(b<0)
        b=-b ,swap(yy1,yy2) ,yy1=-yy1 ,yy2=-yy2 ;
    if(a==0||b==0)
    {
        if(a==0&&b==0)
        {
            if(c==0)
                cout<<(x2-x1+1)*(yy2-yy1+1);
            else puts("0");
        }
        else if(a==0)
        {
            if(c%b==0&&c/b>=yy1&&c/b<=yy2)
                cout<<x2-x1+1;
            else puts("0");
        }
        else
        {
            if(c%a==0&&c/a>=x1&&c/a<=x2)
                cout<<yy2-yy1+1;
            else puts("0");
        }
        return 0;
    }



    gcd(a,b,d,x,y);
    if(c%d)
    {
        puts("0");
        return 0;
    }
    LL tmp=c/d ;
    double addx=b/d ,addy=a/d ;
    x*=tmp ,y*=tmp ;
    LL r=min(floor((x2-x)/addx),floor((y-yy1)/addy)) ,l=max(ceil((x1-x)/addx),ceil((y-yy2)/addy)) ;
    if(r>=l)
        cout<<r-l+1;
    else puts("0");
    return 0;
}

你可能感兴趣的:(扩展欧几里得,sgu,sgu106)