http://codeforces.com/contest/724/problem/C

题目大意:

在一个n*m的盒子里,从(0,0)射出一条每秒位移为(1,1)的射线,遵从反射定律,给出k个点,求射线分别第一次经过这些点的时间。

解法一: (模拟)

射线不管怎么反射,都是和水平方向成45°角的,也就是说每一段射线上的点,横坐标和纵坐标的和或者差相等。 把每一个点放入它所对应的对角线里,然后模拟射线的路径就好。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <map>
  8. #include <cstdlib>
  9. #include <set>
  10. #include <queue>
  11. using namespace std;
  12.  
  13. #define X first
  14. #define Y second
  15. #define Mod 1000000007
  16. #define N 100110
  17. #define M 200110
  18. typedef long long ll;
  19. typedef pair<int,int> pii;
  20.  
  21. const ll INF=1e18;
  22. int n,m,k;
  23. ll ans[N];
  24. pii p[N];
  25. vector<int> dig1[N<<],dig2[N<<];
  26.  
  27. int main()
  28. {
  29. //freopen("in.in","r",stdin);
  30. //freopen("out.out","w",stdout);
  31.  
  32. scanf("%d%d%d",&n,&m,&k);
  33. for (int i=;i<k;i++)
  34. {
  35. scanf("%d%d",&p[i].X,&p[i].Y);
  36. dig1[p[i].X-p[i].Y+N].push_back(i);
  37. dig2[p[i].X+p[i].Y].push_back(i);
  38. ans[i]=INF;
  39. }
  40.  
  41. int x=,y=,d,tx,lx,op=; ll t=;
  42. do
  43. {
  44. lx=x;
  45. if (x==)
  46. {
  47. if (op) d=min(n,m-y),x+=d,y+=d;
  48. else d=min(n,y),x+=d,y-=d;
  49. }
  50. else if (x==n)
  51. {
  52. if (op) d=min(n,y),x-=d,y-=d;
  53. else d=min(n,m-y),x-=d,y+=d;
  54. }
  55. else if (y==)
  56. {
  57. if (op) d=min(m,n-x),x+=d,y+=d;
  58. else d=min(m,x),x-=d,y+=d;
  59. }
  60. else
  61. {
  62. if (op) d=min(m,x),x-=d,y-=d;
  63. else d=min(m,n-x),x+=d,y-=d;
  64. }
  65. if (op)
  66. {
  67. for (int i=;i<dig1[x-y+N].size();i++)
  68. {
  69. tx=p[dig1[x-y+N][i]].X;
  70. ans[dig1[x-y+N][i]]=min(ans[dig1[x-y+N][i]],t+abs(tx-lx));
  71. }
  72. }
  73. else
  74. {
  75. for (int i=;i<dig2[x+y].size();i++)
  76. {
  77. tx=p[dig2[x+y][i]].X;
  78. ans[dig2[x+y][i]]=min(ans[dig2[x+y][i]],t+abs(tx-lx));
  79. }
  80. }
  81. t+=d,op^=;
  82. //cout<<x<<" "<<y<<endl;
  83. }while (!((x== && y==) || (x== && y==m) || (x==n && y==) || (x==n && y==m)));
  84.  
  85. for (int i=;i<k;i++) printf("%I64d\n",ans[i]==INF? -:ans[i]);
  86. return ;
  87. }

解法二:(扩展欧几里得)

水平方向和竖直方向位移可以先分开考虑。

对于水平方向,每秒+1,然后n秒后,碰到墙壁,反弹,然后每秒-1,n秒后再次碰壁,又变成每秒+1.依次类推以2n为周期。

假设横坐标要从0变成x,那么只可能两种情况:

$t \equiv\ x\ (mod\ 2n)$

$t \equiv\ 2n-x\ (mod\ 2n)$

同理纵坐标要从0变成y,也只有两种情况:

$t \equiv\ y\ (mod\ 2m)$

$t \equiv\ 2m-y\ (mod\ 2m)$

同时考虑横纵坐标,一共四种情况,每次相当于解一个线性同余方程组。

解线性同余方程组可以参考这篇: http://www.cnblogs.com/vb4896/p/4009181.html

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <map>
  8. #include <cstdlib>
  9. #include <set>
  10. #include <queue>
  11. using namespace std;
  12.  
  13. #define X first
  14. #define Y second
  15. #define Mod 1000000007
  16. #define N 200110
  17. #define M 200110
  18.  
  19. typedef long long ll;
  20. typedef pair<int,int> pii;
  21.  
  22. const ll INF=4e18;
  23.  
  24. void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
  25. {
  26. if (b==){x=,y=,d=a;}
  27. else
  28. {
  29. ex_gcd(b,a%b,y,x,d);
  30. y-=a/b*x;
  31. }
  32. }
  33.  
  34. ll Solve(ll a1,ll a2,ll m1,ll m2)
  35. {
  36. ll x,y,d,lcm;
  37. ex_gcd(m1,m2,x,y,d);
  38. if ((a2-a1)%d!=) return INF;
  39.  
  40. lcm=m1/d*m2;
  41. x*=(a2-a1)/d;
  42. x=x*m1+a1;
  43. x=(x%lcm)+lcm;
  44. if (x>=lcm) x-=lcm;
  45.  
  46. return x;
  47. }
  48.  
  49. int main()
  50. {
  51. //freopen("in.in","r",stdin);
  52. //freopen("out.out","w",stdout);
  53.  
  54. int n,m,k;
  55. scanf("%d%d%d",&n,&m,&k);
  56. for (int i=;i<=k;i++)
  57. {
  58. ll ans=INF; int x,y;
  59. scanf("%d%d",&x,&y);
  60. ans=min(ans,Solve(x,y,*n,*m));
  61. ans=min(ans,Solve(*n-x,y,*n,*m));
  62. ans=min(ans,Solve(*n-x,*m-y,*n,*m));
  63. ans=min(ans,Solve(x,*m-y,*n,*m));
  64. if (ans==INF) ans=-;
  65. printf("%I64d\n",ans);
  66. }
  67.  
  68. return ;
  69. }

再来一发福利: hdu 5114   和这题的方法类似,可以顺手切了

http://acm.hdu.edu.cn/showproblem.php?pid=5114

题目大意:

n*m的盒子里给出2个球的坐标,2个球一开始速度都是(1,1),遵守反射定律,求相遇点的坐标。

思路:

1.首先相遇点的坐标要么是整数,要么是n+0.5的形式,所以可以实现把所有坐标乘以2,可以避免小数,最后除以2就好。

2.同样横纵坐标分开考虑。

不难求出横纵坐标第一次相同的时间分别为$\frac{2n-x_1-x_2}{2}$   $\frac{2m-y_1-y_2}{2}$

然后水平方向相遇的周期为n,竖直方向周期为m。所以

$t \equiv\ \frac{2n-x_1-x_2}{2}\ (mod\ n)$

$t \equiv\ \frac{2m-y_1-y_2}{2}\ (mod\ m)$

解出t,然后模拟一下就可以求出相遇点的坐标了。

代码:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <cstring>
  5. using namespace std;
  6.  
  7. #define N 1010
  8. typedef long long ll;
  9.  
  10. int T,n,m,x1,x2,y1,y2;
  11.  
  12. void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
  13. {
  14. if (b==) {x=,y=,d=a;}
  15. else
  16. {
  17. ex_gcd(b,a%b,y,x,d);
  18. y-=a/b*x;
  19. }
  20. }
  21.  
  22. ll Solve()
  23. {
  24. if (x1==x2 && y1==y2) return ;
  25. if (x1==x2) return (*m-y1-y2)/;
  26. if (y1==y2) return (*n-x1-x2)/;
  27.  
  28. ll t1=(*n-x1-x2)/,t2=(*m-y1-y2)/,x,y,d;
  29. ex_gcd(n,m,x,y,d);
  30. if ((t2-t1)%d!=) return -;
  31. x*=(t2-t1)/d;
  32.  
  33. ll lcm=n/d*m;
  34. ll ans=(x*n+t1)%lcm;
  35. if (ans<) ans+=lcm;
  36. return ans;
  37. }
  38.  
  39. int main()
  40. {
  41. //freopen("in.in","r",stdin);
  42. //freopen("out.out","w",stdout);
  43.  
  44. scanf("%d",&T);
  45. for (int cas=;cas<=T;cas++)
  46. {
  47. printf("Case #%d:\n",cas);
  48. scanf("%d%d",&n,&m); n<<=,m<<=;
  49. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  50. x1<<=,y1<<=,x2<<=,y2<<=;
  51. ll t=Solve();
  52. if (t==-) {printf("Collision will not happen.\n"); continue;}
  53.  
  54. int tx=t%(*n),ty=t%(*m),x=x1,y=y1;
  55. if (x+tx<=n) tx=x+tx;
  56. else if (*n-x-tx>=) tx=*n-x-tx;
  57. else tx-=n+n-x;
  58.  
  59. if (y+ty<=m) ty=y+ty;
  60. else if (*m-y-ty>=) ty=*m-y-ty;
  61. else ty-=m+m-y;
  62.  
  63. printf("%.1lf %.1lf\n",tx/2.0,ty/2.0);
  64. }
  65.  
  66. return ;
  67. }

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C.Ray Tracing (模拟或扩展欧几里得)的更多相关文章

  1. CF Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)

    1. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort    暴力枚举,水 1.题意:n*m的数组, ...

  2. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)D Dense Subsequence

    传送门:D Dense Subsequence 题意:输入一个m,然后输入一个字符串,从字符串中取出一些字符组成一个串,要求满足:在任意长度为m的区间内都至少有一个字符被取到,找出所有可能性中字典序最 ...

  3. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort

    链接 题意:输入n,m,表示一个n行m列的矩阵,每一行数字都是1-m,顺序可能是乱的,每一行可以交换任意2个数的位置,并且可以交换任意2列的所有数 问是否可以使每一行严格递增 思路:暴力枚举所有可能的 ...

  4. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C. Ray Tracing

    我不告诉你这个链接是什么 分析:模拟可以过,但是好烦啊..不会写.还有一个扩展欧几里得的方法,见下: 假设光线没有反射,而是对应的感应器镜面对称了一下的话 左下角红色的地方是原始的的方格,剩下的三个格 ...

  5. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E. Goods transportation (非官方贪心解法)

    题目链接:http://codeforces.com/contest/724/problem/E 题目大意: 有n个城市,每个城市有pi件商品,最多能出售si件商品,对于任意一队城市i,j,其中i&l ...

  6. Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A. Checking the Calendar(水题)

    传送门 Description You are given names of two days of the week. Please, determine whether it is possibl ...

  7. Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort(暴力)

    传送门 Description You are given a table consisting of n rows and m columns. Numbers in each row form a ...

  8. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B

    Description You are given a table consisting of n rows and m columns. Numbers in each row form a per ...

  9. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A

    Description You are given names of two days of the week. Please, determine whether it is possible th ...

随机推荐

  1. append追加的使用

    #!/usr/bin/env python def fun(arg) : ret = [] for i in range(len(arg)) : if i % 2 ==1 : ret.append(a ...

  2. 学习git与github的二三事 (一)

    前一段时间看到了一个参加机器人比赛的同学写的经验之谈,他提到了在比赛时,希望同学们学习一下git来管理代码,于是我就某度了一下,发现了廖雪峰老师的网站,受益匪浅,持续学习中,拜谢大神,顺便记录一下自己 ...

  3. 【2014-05-06】C++ 设计模式----单例模式

    1.何为单例模式? 单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点(static).可能有人会想这和全局变量有什么区别呢? 通常我们可以让一个全局成员变量使得一个 ...

  4. Python notes

    1. range()函数的使用: a = range(n) # a = range(0,n) b = range(m,n) # b = range(m,n) alist = list(a) # ali ...

  5. JAVA 1.1

    1. JASE : J2SE 这个就是我们现在在学的东西,他是一切Java的核心基础 JAME :J2ME : 他是Java的一个微型版,主要用来做移动开发 JAEE :J2EE Java企业版本,主 ...

  6. python获取时间

    获取当前时间,和当前UTC时间 #!/usr/bin/env python #_*_ encoding:utf-8_*_ import datetime import time utctime = d ...

  7. Exit code from container executor initialization is : 24 ExitCodeException exitCode=24: Configuration file ../etc/hadoop/container-executor.cfg not found.

    /etc/hadoop/conf的软链接(/etc/hdfs/conf)不正确,应该是/etc/yarn/conf

  8. test 2016-12-28

    // dpm(variable_get('node_submitted_page'));// //0// dpm(variable_get('language_count'));// //i3 = i ...

  9. 在重新生成解决方案时,出现的错误:无法将文件“obj\x86\Debug\*.exe”复制到“obj\Debug\*.exe”。文件正由另一进程使用,因此该进程无法访问此文件

    此例是VS2010的CS项目. 在重新生成解决方案时,出现的错误. 解决步骤:先关闭解决方案,再在项目文件下的bin\Debug\*.exe删除这类之前生成得.exe文件,再在VS2010下重新生成.

  10. 【javascript】作用域和闭包浅析

    作用域 分全局作用域和局部作用域 全局作用域:函数外部定义的变量,可以被整个program的各成员参照利用. 局部作用域:函数内部定义的变量,仅供该函数的各成员参照利用. var val=1; //全 ...