UVA 11768 Lattice Point or Not(扩展欧几里德)

将直线转化为ax + by = c的形式,然后扩展欧几里得求在[x1, x2]之间的解

对直线与坐标轴平行的特判

 

调试了好长时间,注意:

1 正负数转化为整型的处理

2 注意判断有无解

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
const int N = 1008, INF = 0x3F3F3F3F;
const double eps = 1e-6, meps = 1e-7;
LL Ext_gcd(LL a,LL b,LL &x,LL &y){//扩展欧几里得
   if(b==0) { x=1, y=0; return a; }
   LL ret= Ext_gcd(b,a%b,y,x);
   y-= a/b*x;
   return ret;
}

LL gcd(LL a, LL b){
	while(b){
		LL t = a % b;
		a = b;
		b = t;
	}
	return a;
}


LL  cal(LL x1, LL x2, LL x, LL mod){
    if(x1 > x2){
        return 0;
    }
    if(x >= x1 && x <= x2){
        return (x - x1) / mod + 1 + (x2 - x) / mod;
    }
    if(x < x1){
        return (x2 - x) / mod - (x1 - 1 - x) / mod;
    }
    return (x - x1) / mod - (x - x2 - 1) / mod;

}
LL toLL(double x){
    if(x > 0){
        return x + eps;
    }
    if(x < 0){
        return x - eps;
    }
    return 0;
}
int main(){
    double t1, t2, t3, t4;
    int t;
    scanf("%d", &t);
    while(t--){
    	scanf("%lf %lf %lf %lf", &t1, &t2, &t3, &t4);
    	if(abs(t1 - t3) < eps){
            if(abs(t1 - (LL)t1) < eps){
                double t22 = min(t2, t4);
                double t44 = max(t2, t4);
                printf("%lld\n", cal((LL)ceil(t22), (LL)floor(t44), (LL)ceil(t22), 1));
            }else{
                printf("0\n");
            }
            continue;
    	}

        if(abs(t2 - t4) < eps){
            if(abs(t2 - (LL)t2) < eps){
                double t11 = min(t1, t3);
                double t33 = max(t1, t3);
                printf("%lld\n", cal((LL)ceil(t11), (LL)floor(t33), (LL)ceil(t11), 1));
            }else{
                printf("0\n");
            }
            continue;
    	}

    	LL x1 = toLL(t1 * 10), y1 = toLL(t2 * 10), x2 = toLL(t3 * 10), y2 = toLL(t4 * 10);

    	//cout<<x1<<" "<<y1<<"  "<<x2<<"  "<<y2<<"\n";

        if(x1 > x2){
            swap(x1, x2);
            swap(y1, y2);
        }
        LL a = (y2 - y1) * 10, b = (x1 - x2) * 10;
        LL c = x1 * y2 - x2 * y1;
        LL gc = gcd(gcd(a, b), c);
        a /= gc;
        b /= gc;
        c /= gc;

        //cout<<a<<"  "<<b<<"  "<<c<<"  ***\n";
        if(c % gcd(a, b)){
            printf("0\n");
            continue;
        }

        //cout<<a * t1 + b * t2 - c<<" aa\n";
        //cout<<a * t3 + b * t4 - c<<" aa\n";
        LL x, y;
        Ext_gcd(a, b, x, y);
        //cout<<x<<"  "<<y<<" xy\n";
        x = c / gcd(a, b) * x;
        //cout<<x<<"  spe\n";
        if(t1 > t3){
            swap(t1, t3);
        }
        printf("%lld\n",cal((LL)ceil(t1), (LL)floor(t3), x, abs(b / gcd(a, b))));
        //cout<<tp<<"  cal\n";
    }

    return 0;
}

  

转载于:https://www.cnblogs.com/IMGavin/p/6035679.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值