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

题目大意:

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

解法一: (模拟)

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

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
#include <queue>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 100110
#define M 200110
typedef long long ll;
typedef pair<int,int> pii; const ll INF=1e18;
int n,m,k;
ll ans[N];
pii p[N];
vector<int> dig1[N<<],dig2[N<<]; int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d%d%d",&n,&m,&k);
for (int i=;i<k;i++)
{
scanf("%d%d",&p[i].X,&p[i].Y);
dig1[p[i].X-p[i].Y+N].push_back(i);
dig2[p[i].X+p[i].Y].push_back(i);
ans[i]=INF;
} int x=,y=,d,tx,lx,op=; ll t=;
do
{
lx=x;
if (x==)
{
if (op) d=min(n,m-y),x+=d,y+=d;
else d=min(n,y),x+=d,y-=d;
}
else if (x==n)
{
if (op) d=min(n,y),x-=d,y-=d;
else d=min(n,m-y),x-=d,y+=d;
}
else if (y==)
{
if (op) d=min(m,n-x),x+=d,y+=d;
else d=min(m,x),x-=d,y+=d;
}
else
{
if (op) d=min(m,x),x-=d,y-=d;
else d=min(m,n-x),x+=d,y-=d;
}
if (op)
{
for (int i=;i<dig1[x-y+N].size();i++)
{
tx=p[dig1[x-y+N][i]].X;
ans[dig1[x-y+N][i]]=min(ans[dig1[x-y+N][i]],t+abs(tx-lx));
}
}
else
{
for (int i=;i<dig2[x+y].size();i++)
{
tx=p[dig2[x+y][i]].X;
ans[dig2[x+y][i]]=min(ans[dig2[x+y][i]],t+abs(tx-lx));
}
}
t+=d,op^=;
//cout<<x<<" "<<y<<endl;
}while (!((x== && y==) || (x== && y==m) || (x==n && y==) || (x==n && y==m))); for (int i=;i<k;i++) printf("%I64d\n",ans[i]==INF? -:ans[i]);
return ;
}

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

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

对于水平方向,每秒+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

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
#include <queue>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 200110
#define M 200110 typedef long long ll;
typedef pair<int,int> pii; const ll INF=4e18; void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
{
if (b==){x=,y=,d=a;}
else
{
ex_gcd(b,a%b,y,x,d);
y-=a/b*x;
}
} ll Solve(ll a1,ll a2,ll m1,ll m2)
{
ll x,y,d,lcm;
ex_gcd(m1,m2,x,y,d);
if ((a2-a1)%d!=) return INF; lcm=m1/d*m2;
x*=(a2-a1)/d;
x=x*m1+a1;
x=(x%lcm)+lcm;
if (x>=lcm) x-=lcm; return x;
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=k;i++)
{
ll ans=INF; int x,y;
scanf("%d%d",&x,&y);
ans=min(ans,Solve(x,y,*n,*m));
ans=min(ans,Solve(*n-x,y,*n,*m));
ans=min(ans,Solve(*n-x,*m-y,*n,*m));
ans=min(ans,Solve(x,*m-y,*n,*m));
if (ans==INF) ans=-;
printf("%I64d\n",ans);
} return ;
}

再来一发福利: 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,然后模拟一下就可以求出相遇点的坐标了。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std; #define N 1010
typedef long long ll; int T,n,m,x1,x2,y1,y2; void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
{
if (b==) {x=,y=,d=a;}
else
{
ex_gcd(b,a%b,y,x,d);
y-=a/b*x;
}
} ll Solve()
{
if (x1==x2 && y1==y2) return ;
if (x1==x2) return (*m-y1-y2)/;
if (y1==y2) return (*n-x1-x2)/; ll t1=(*n-x1-x2)/,t2=(*m-y1-y2)/,x,y,d;
ex_gcd(n,m,x,y,d);
if ((t2-t1)%d!=) return -;
x*=(t2-t1)/d; ll lcm=n/d*m;
ll ans=(x*n+t1)%lcm;
if (ans<) ans+=lcm;
return ans;
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d",&T);
for (int cas=;cas<=T;cas++)
{
printf("Case #%d:\n",cas);
scanf("%d%d",&n,&m); n<<=,m<<=;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1<<=,y1<<=,x2<<=,y2<<=;
ll t=Solve();
if (t==-) {printf("Collision will not happen.\n"); continue;} int tx=t%(*n),ty=t%(*m),x=x1,y=y1;
if (x+tx<=n) tx=x+tx;
else if (*n-x-tx>=) tx=*n-x-tx;
else tx-=n+n-x; if (y+ty<=m) ty=y+ty;
else if (*m-y-ty>=) ty=*m-y-ty;
else ty-=m+m-y; printf("%.1lf %.1lf\n",tx/2.0,ty/2.0);
} return ;
}

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. C# HttpWebRequest GET HTTP HTTPS 请求

    下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中发送GET/HTTP/HTTPS请求,因为有的时候需要获取认证信息(如Cookie),所以返回的是HttpWebResponse ...

  2. Word 宏命令大全

      1.   为宏命令指定快捷键.在WORD中,操作可以通过菜单项或工具栏按钮实现,如果功能项有对应的快捷键的话,利用快捷键可以快速实现我们需要的功能.如最常见的CTRL+O.CTRL+A等等.WOR ...

  3. windows server 2012 r2 远程桌面连接指南

    具体详情请阅览文档  http://pan.baidu.com/s/1jHTCpW6 windows server 2012 r2 远程桌面连接指南 - 作者 rick·bao - 日期 2016-0 ...

  4. AFN设置请求超时时间

    进入AFURLRequestSerialization.m 找到 - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLSt ...

  5. Arduino 极速入门系列 - 光控灯(2) - 关于开关,上拉、下拉电阻那些事

    接上篇,这次继续讲解光控灯的另外两个组成部分 - 开关和光敏电阻,光控灯里面将会有自锁开关按钮和光敏电阻.这此主要给新玩电子的朋友解释一下开关按钮的做法. 开关按钮的引脚电平读取问题 - 新手专用 我 ...

  6. es6还欠完善的地方

    const的可变性 const用于声明常量. 什么是常量,声明后的值不可更改. 对于值类型,比如string,number等等.const声明确实有效. const str = "strin ...

  7. Jekyll教程——精心收藏

    以前总想搭建一个自己的个人网站,由于不懂php后台,所以在点点网开过自己的博客,后来慢慢向程序员转变,点点网的博客已经不能满足这个职业特定的需求,于是用worldpress搭建了自己的第一个网站,鼓捣 ...

  8. js中call、apply、bind的用法

    原文链接:http://www.cnblogs.com/xljzlw/p/3775162.html var zlw = { name: "zlw", sayHello: funct ...

  9. python爬虫实战(一)——实时获取代理ip

    在爬虫学习的过程中,维护一个自己的代理池是非常重要的. 详情看代码: 1.运行环境 python3.x,需求库:bs4,requests 2.实时抓取西刺-国内高匿代理中前3页的代理ip(可根据需求自 ...

  10. JQuery实现table分页

    1.直接贴代码: ; //每页显示的记录条数 ; //显示第curPage页 var len; //总行数 var page; //总页数 $(function(){ len =$(; //去掉表头 ...