牛客周赛 Round 69:C仰望水面的歪

题目描述

        小歪正在水底潜水,他所在的位置距离水面的直线距离为  。小歪有一个神奇的激光装置,激光射向水面后会发生全反射现象。
        以小歪所在的位置为原点建立三维坐标轴,小歪的坐标即为 (0,0,0) 。在水中,有一些坐标需要小歪使用激光击中,第 i 个坐标使用 (xi,yi,zi)表示。求解,对于每一个坐标,小歪需要以什么向量方向射出激光,使得经过一次水面全反射后恰好击中它。

输入描述:

第一行输入两个整数 n,h(1≦n≦100; 1≦h≦109) 代表需要击中的坐标位置数量、距离水面的距离。随后 n 行,每行输入三个整数 x,y,z(1≦x,y≦109;−109≦z≦h)代表需要击中的坐标。

输出描述:

对于每一个坐标,在一行上输出三个整数 i,j,k代表射出向量方向,你需要保证 gcd⁡(i,j,k)=1 。

示例:

输入

2 5
3 3 2
4 4 0

输出

3 3 8
2 2 5

解题思路:

        激光入射的路径是从小歪的位置(0,0,0) 出发,反射后进入目标点。水面对称性说明,目标点在水面上的“对称点” (x,y,2h−z) 会是激光直线的延长线上的点。因此,只需要求解从 (0,0,0) 到对称点 (x,y,2h−z) 的向量方向,并化简为最简整数比即可。

代码:

#include <stdio.h>
#include <math.h>
//计算两个数的最大公约数
long long gcd(long long a,long long b)
{
    if(a==0)
        return fabs(b);
    if(b==0)
        return fabs(a);
    while(b)
    {
        int r=a%b;
        a=b;
        b=r;
    }
    return fabs(a);
}

//计算三个数的最大公约数
long long gcd3(long long  a,long long  b,long long  c)
{
    return gcd(gcd(a,b),c);
}

int main ()
{
    long long n,h;
    scanf("%lld %lld",&n,&h);
    while(n--)
    {
        long long x,y,z;
        scanf("%lld %lld %lld",&x,&y,&z);
        long long X,Y,Z;
        X=x,Y=y,Z=2*h-z;
        long long num=gcd3(X,Y,Z);
        X/=num,Y/=num,Z/=num;
        printf("%lld %lld %lld\n",X,Y,Z);
    }
        
}

注意事项:

        1.在处理最大公约数时,需要考虑负数或 0 的情况,可能导致化简结果错误。

        2.计算2*h−z 时可能会导致溢出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值