[ACMICPC 2014 Beijing Onsite] C Collision
2014-12-02 05:35
309 查看
Collision
题目大意
给一个 P*Q 的矩形,两个小球分别以 (1 , 1) 的方向在 (a,x) (b,y) 点开始运动,碰到墙壁依照镜面反射。问是否能相遇如果相遇输出第一个相遇地点。做法
这个题目首先请看我出过的一个题目:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2087 。我们先看 X 坐标,因为小球的速度不变,很容易能得到每个球在行走 2*P 的距离之后对于 X 坐标来说,他们相遇的时刻是一个循环。也就是一定会在 (2k)*P+U 和 (2k*Q) + V 处相遇。对于 Y 坐标亦然。那我们就来计算 U 和 V 的位置。
首先我们把问题抽象为一维的问题—— 有一个 0~P 的坐标轴,有两个质点在 a 和 b (a<b),速度都是 1 , 碰到端点原速返回。
那么第一个相遇的情况U: A 点走了一段距离还没有到 P 点,而 B 点走了一段距离碰到 P 点之后折回一段距离碰到了 A 点。
如果设时间为 t , 很容易列出一个方程 —— a+t <相遇点的坐标U> = P - (b+t-P <折回的距离>)<相遇点的坐标U> , 化简为: t = P - (a + b)/2 。因此下一次在 U 点相遇的时间为 t + 2*P(两个球又同时走了一个折回相遇) , t + 4 * P ...... t + (2k)*P
对于第二个相遇的情况V: A 点走了一段距离碰到 P 之后折回没有碰到 0 点之前与 B 相遇。 B 碰到 P 之后折回,又碰到 0 之后又折回,再碰到 A。
如果设时间为t , 很容易列出一个方程 —— P-(a+t-P<V 点距离P点距离>)<V点坐标> = (b+t - 2*P) ,化简为:t = 2P - (a + b)/2 。 因此下一次在 V 点相遇的时间为 t + 2*P(两个球又同时走了一个折回相遇) , t + 4 * P ...... t + (2k)*P.
我们看现在就有一个很好的性质!!!那就是相遇的时间可以简化为 t = P - (a+b)/2 + k*P (k >= 0)
同理可得,对于 Y 坐标,相遇时间可以简化为 : t = Q - (x+y)/2 + kk * Q (kk >= 0)
联立两个方程,化简可得:k*P - kk * Q = (P - Q) - ( (a+b) / 2 - (x + y) / 2)
那么我们就肯容易发现这个东西的长相不是 Ax + By + C = 0 么???!!! 这是啥?扩展GCD啊!
我们设 C = (P - Q ) - ( (a+b) / 2 - (x + y) / 2) , A = P , B = -Q . 然后利用 扩展 GCD 求出一组解。因为他要求第一个相遇位置,那么我们就调整一下答案,求出最小整数解就好了呀。
但是这个题目还有几个坑:
0. 因为等式左边是整数,那么右边必须也是整数。所以如果 C 不是整数,输出 No 就好了。
1. 如果a=b , x=y的话,那么一开始就相遇了,因此直接输出 (a,x) 点即可。
2. 如果a=b , x=y的话,只用看X坐标或者Y坐标即可,输出第一个出现的位置就行了。
3. 我们知道 k*P - kk*Q 能形成的最小正整数解是 GCD(P,Q) , 那么如果 C 不是 GCD(P,Q) 的倍数的话输出 NO就行了。
4. 对于最普遍的情况,我们按照 C 的正|负分类。以正数为例,设 r = extendGCD(P , -Q , n , m) ,那么一组普通的解就是 k = n * C / r , kk = m * C / r . 然后我们按照 P 和 Q 的倍数进行调整(见 f 函数)。我们得到最小解 k 之后(代码里面是 pp ) , 那么我们带入原式就能得到行走的时间 t 。 然后分别在 P 和 Q 上映射到坐标即可。
Code(写的又臭又长真是抱歉 T^T
#include <functional> #include <algorithm> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cstring> #include <cassert> #include <cstdio> #include <string> #include <vector> #include <bitset> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> using namespace std; #define DO(n) for ( int ____n ## __line__ = n; ____n ## __line__ -- ; ) #define ALL(A) A.begin(), A.end() #define BSC(A, x) (lower_bound(ALL(A), x) - A.begin()) #define CTN(T, x) (T.find(x) != T.end()) #define SZ(A) int(A.size()) #define PB push_back #define MP(A, B) make_pair(A, B) #define fi first #define se second typedef long long LL; typedef vector<int> VI; typedef map<int, int> MII; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));} template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));} template<class T> inline void CLR(T &A){A.clear();} //} /** Constant List .. **/ //{ const int dx4[] = {-1, 0, 1, 0}; const int dy4[] = {0, 1, 0, -1}; const int dx8[] = {-1, 0, 1, 0 , -1 , -1 , 1 , 1}; const int dy8[] = {0, 1, 0, -1 , -1 , 1 , -1 , 1}; const int dxhorse[] = {-2 , -2 , -1 , -1 , 1 , 1 , 2 , 2}; const int dyhorse[] = {1 , -1 , 2 , -2 , 2 ,-2 , 1 ,-1}; const int MOD = 1000000007; //int MOD = 99990001; const int INF = 0x3f3f3f3f; const LL INFF = 1LL << 60; const double EPS = 1e-9; const double OO = 1e15; const double PI = acos(-1.0); //M_PI; //} template<class T> inline void checkMin(T &a,const T b){if (b<a) a=b;} template<class T> inline void checkMax(T &a,const T b){if (a<b) a=b;} //} template<class T> inline T low_bit(T x) {return x & -x;} /*****************************************************************/ typedef long long typec; typedef double DB; const DB eps = 1e-9; int dblcmp(DB d){ return d < -eps ? -1 : d > eps; } typec GCD(typec a, typec b) { return b ? GCD(b, a % b) : a; } typec extendGCD(typec a, typec b, typec& x, typec& y) { if(!b) return x = 1, y = 0, a; typec res = extendGCD(b, a % b, x, y), tmp = x; x = y, y = tmp - (a / b) * y; return res; } void f(DB &x , DB &y , LL ax , LL ay){ if (x > eps){ DB add = (x - fmod(x , (DB)abs(ax)) ) / abs(ax); if (ax > 0){ x -= add * ax; y -= add * ay; } else{ x += add * ax; y += add * ay; } } if (y < -eps){ // LL add = (-y) / abs(ay) + ((-y) % abs(ay) != 0); DB add = (-y - fmod(-y , (DB)abs(ay)) ) / (DB)abs(ay) + (dblcmp(fmod(-y , DB(abs(ay)))) != 0); if (ay > 0){ x += add * ax; y += add * ay; } else{ x -= add * ax; y -= add * ay; } } if (x < -eps){ // LL add = (-x) / abs(ax) + ((-x) % abs(ax) != 0); DB add = (-x - fmod(-x , (DB)abs(ax)) ) / (DB)abs(ax) + (dblcmp(fmod(-x , DB(abs(ax)))) != 0); if (ax > 0){ x += add * ax; y += add * ay; } else{ x -= add * ax; y -= add * ay; } } } LL P , Q , a , b , x , y; int Case; void solve(){ scanf("%I64d%I64d%I64d%I64d%I64d%I64d" , &P , &Q , &a , &x , &b , &y); if (a == b && x == y){ printf("Case #%d:\n" , ++Case); printf("%.1lf %.1lf\n" , 1. * a , 1. * x); return; } if (a == b){ printf("Case #%d:\n" , ++Case); DB t = Q - 1. * (x + y) / 2.; DB ans = a + t; ans = fmod(ans , 2. * P); if (dblcmp(ans - P) >= 0) ans = 2. * P - ans; printf("%.1lf " , ans); ans = y + t; ans = fmod(ans , 2. * Q); if (dblcmp(ans - Q) >= 0) ans = 2. * Q- ans; printf("%.1lf\n" , ans 4000 ); return; } if (x == y){ printf("Case #%d:\n" , ++Case); DB t = P - 1. * (a + b) / 2.; DB ans = a + t; ans = fmod(ans , 2. * P); if (dblcmp(ans - P) >= 0) ans = 2. * P - ans; printf("%.1lf " , ans); ans = y + t; ans = fmod(ans , 2. * Q); if (dblcmp(ans - Q) >= 0) ans = 2. * Q - ans; printf("%.1lf\n" , ans); return; } if (abs(a + b - x - y) % 2 == 1){ printf("Case #%d:\nCollision will not happen.\n" , ++Case); return; } LL C = Q - P + (a + b - x - y) / 2; if (C % __gcd(P , Q) != 0){ printf("Case #%d:\nCollision will not happen.\n" , ++Case); return; } LL n , m; printf("Case #%d:\n" , ++Case); // cout << C << endl; if (C >= 0){ LL r = extendGCD(P , -Q , n , m); LL multi = C / r; DB pp = n , qq = m ; pp *= multi , qq *= multi; // cout << p << ' ' << q; f(pp , qq , Q / r , P / r); // cout << pp << ' ' << qq << endl; DB ans = pp * P + P - 1. * (a + b) / 2.; ans += a; ans = fmod(ans , 2. * P); if (dblcmp(ans - P) >= 0) ans = 2. * P - ans; printf("%.1lf " , ans); ans = qq * Q + Q - 1. * (x + y) / 2.; ans += x; ans = fmod(ans , 2. * Q); if (dblcmp(ans - Q) >= 0) ans = 2. * Q - ans; printf("%.1lf\n" , ans); } else{ LL r = extendGCD(Q , -P , m , n); LL multi = -C / r; DB pp = n , qq = m ; pp *= multi , qq *= multi; // cout << p << ' ' << q; f(qq , pp , P / r , Q / r); DB ans = 0; // cout << pp << ' ' << qq << endl; ans = pp * P + P - 1. * (a + b) / 2.; ans += a; ans = fmod(ans , 2. * P); if (dblcmp(ans - P) >= 0) ans = 2. * P - ans; printf("%.1lf " , ans); ans = qq * Q + Q - 1. * (x + y) / 2.; ans += x; ans = fmod(ans , 2. * Q); if (dblcmp(ans - Q) >= 0) ans = 2. * Q - ans; printf("%.1lf\n" , ans); } } int main(){ Case = 0; int _; cin >> _; while(_--) solve(); }
相关文章推荐
- ACMICPC 2014 Shanghai Onsite 总结
- ACMICPC 2013 Nanjing Onsite 总结
- 2014_guangzhou_onsite
- [LA7139 Rotation(2014 shanghai onsite)]二维树状数组
- Beijing onsite scl version 1
- ACMICPC 2013 Changsha Onsite 总结
- [uva_la7146 Defeat the Enemy(2014 shanghai onsite)]贪心
- 2014-Aisa-Shanghai-onsite
- Facebook SDE onsite面经
- 2015 ACM/ICPC Asia Regional Shanghai On-Site 赛后训练赛一!
- Will Be write on this site!
- HDU 5514 Collision(扩展欧几里得+解方程)——2014ACM/ICPC亚洲区北京站
- Our site provides essential information on pilates yoga mat.
- [杂题] Codechef SnackDown 2017 Onsite Final #MINIMAX Minimax
- My project was published on microsoft web site as case study!
- 2014_beijing_onsite
- 【枚举】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem G. Equation
- bzoj4533 [BeiJing2014 WinterCamp] 数据
- 2014北京邀请赛 F Football on Table
- bugfree3出现 /bugfree/site/login was not found on this server. 解决方案