codefoces 724 c Ray Tracing (扩展欧几里德)

106 篇文章 0 订阅
51 篇文章 0 订阅

题意:

给定一个矩形,长n宽m, 一束光从矩形的一个顶点发射,角度为45度,遇到墙壁则反射, 只有遇到顶点时被吸收,  给你k个光传感器,光传播的速度是根号二m/s,问经过多少时间,光经过这个传感器, 若不能经过,则输出-1。


思路:

将矩形对称展开,把所有反射当做穿过看待,容易想到光在横纵坐标都为maxnx= m*n/gcd(m,n)(m,n的最小公倍数) 处吸收,因为光总是沿着y=x这条直线传播。所以如果光能经过那些传感器,传感器的坐标一定在(0,0)到 (maxnx, maxnx)之间, 即它们的坐标一定能化成(2kn±x, 2sm±y),满足2kn±x= 2sm±y,求出这个方程使2kn±x最小的解即可.具体用扩展欧几里得,求得k,然后让k化成最小,在求出2kn±x,即得解. 需要注意取模时要判断被取模的数是否为正.


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
long long n, m;
void exgcd(long long a, long long b, long long &d, long long &x, long long &y)
{
    if(!b){d=a;x=1; y=0;}
    else {exgcd(b, a%b, d, y, x); y-=x*(a/b); }
}
long long equation(long long a, long long b, long long c, long long &x, long long &y)
{
    long long g;
    exgcd(a,b,g,x,y);
    if(c%g){ return -1;}
    x*=c/g;
    long long ran=b/g; 
    if(ran<0)ran=-ran;
    x=(x%ran+ran)%ran; <span style="font-family: Arial, Helvetica, sans-serif;">//(a/g)*x+(b/g)*y=1;让x-b/g,y+a/g,等式仍成立, 所有x要最小只需对b/g取模即可,另外防止x是负数,所以还得再加一次b/g</span>

    return 0;
}
long long que(long long x, long long y, long long maxn)
{
    long long k, s;
    if(equation(2*n, -2*m, y-x, k, s)==-1){return maxn+1;}
    long long tx;
    tx=2*k*n+x;
    if(tx<0 || tx>maxn){ return maxn+1;}
    return tx;
}
long long solve(long long x, long long y)
{
    long long maxn=m*n;
    long long res=maxn+1;
    res=min(res, que(x, y, maxn)); //比较四种情况哪个解最小
    res=min(res, que(x, -y, maxn));
    res=min(res, que(-x, y, maxn));
    res=min(res, que(-x, -y, maxn));
    if(res==maxn+1)return -1;  //若答案超过maxn,必然不能经过.
    return res;
}
int main()
{
    int k;
    scanf("%lld%lld%d", &n, &m, &k);
    int i;
    for(i=0; i<k; i++)
    {
        long long x, y;
        scanf("%lld%lld", &x, &y);
        printf("%lld\n", solve(x,y));
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值