• C. Ray Tracing——披着搜索外衣的扩展欧几里得


    【题目大意】

    给你一个n*m的矩形,光线从(0,0)出发,沿右上方向以每秒根号2米的速度运动,碰到矩形边界就会反弹(符合物理规律的反弹),询问k个点,这些点都在矩形内部且不在矩形边界上,求光经过这些点的最小时间。如果光不会经过这个点,输出-1.

    【数据范围】

    0<m,n,k<=100000

    【吐槽】

    最后1个小时都砸这道题上了,一直是搜索/模拟 的思路,然而正解是扩展欧几里得。(据说模拟也是可以的,然而我不会,sro_姬树流_orz)

    【题解】

    把矩形对称展开,最后小球在横纵坐标均为maxx=mn/gcd(m,n)处被吸收。 

    原坐标为(x,y)的小球经过轴对称展开,其坐标为(2kn±x,2sm±y),k,s.要使得在吸收前经过点,则坐标必须在线段(0, 0)到(maxx, mxx)之间。 

    即要解方程2kn±x=2sm±y,求为正最小的2kn±x。利用扩展欧几里得解方程。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<ctime>
     7 #include<algorithm>
     8 using namespace std;
     9 long long n,m,k,aa,bb,maxx;
    10 inline long long read()
    11 {
    12     long long x=0,f=1;  char ch=getchar();
    13     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    14     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    15     return x*f;
    16 }
    17 long long exgcd(long long a,long long b,long long &x,long long &y)
    18 {
    19     if(b==0)  {x=1; y=0; return a;}
    20     long long r=exgcd(b,a%b,y,x);
    21     y-=a/b*x;
    22     return r;
    23 }
    24 long long gao(long long x,long long y)
    25 {
    26     long long c=x+y,dx,dy;
    27     long long r=exgcd(aa,bb,dx,dy);
    28     if(c%r)  return maxx+1;
    29     long long mo=bb/r;   dx*=c/r;
    30     if(mo<0)  mo=-mo;
    31     dx=(dx%mo+mo)%mo;
    32     long long ans=2*n*dx-x;
    33     if(ans<0||ans>maxx)  return maxx+1;
    34     return ans;
    35 }
    36 long long minn(long long a,long long b)  {return a<b?a:b;}
    37 long long solve(long long x,long long y)
    38 {
    39     long long r=__gcd(n,m);
    40     maxx=n*m/r;
    41     long long ans=maxx+1;
    42     ans=minn(ans,gao(x,y));
    43     ans=minn(ans,gao(x,-y));
    44     ans=minn(ans,gao(-x,y));
    45     ans=minn(ans,gao(-x,-y));
    46     if(ans==maxx+1)  return -1;
    47     else return ans;
    48 }
    49 int main()
    50 {    
    51     //freopen("cin.in","r",stdin);
    52     //freopen("cout.out","w",stdout);
    53     n=read();  m=read();  k=read();
    54     aa=2*n;  bb=-2*m;
    55     for(int i=1;i<=k;i++)
    56     {
    57         long long x=read(),y=read();
    58         printf("%I64d
    ",solve(x,y));
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    接口测试断言详解(Jmeter)
    接口测试参数化详解(Jmeter)
    记一次线上内存泄漏问题的排查过程
    BI入门经典(转载)
    图形初阶
    数据的输入
    来自 Google 的 R 语言编码风格指南
    提醒程序员注意的一些事项--R
    R语言-attach、detach、with
    R数据类型
  • 原文地址:https://www.cnblogs.com/chty/p/5943804.html
Copyright © 2020-2023  润新知