跳跳-题解
cf 1200
题目描述
平面上给定了一些整点(横纵坐标均为整数的点),被称为 “魔法阵”。魔法少女派派想要在各魔法阵之间传送,每一次传送,她将使用下面的方式:
- 刚开始,派派已经位于某传送阵之上;
- 如果派派掌握一种魔法 (A,B),其中 A,B 均为整数。使用一次这个魔法可以让派派从任意整点 (X,Y) 瞬间移动至 (X+A,Y+B);
- 选择一种魔法并开始传送,在一次传送过程中可以使用多次该魔法,但在抵达下一个传送阵之前仅能使用这一种魔法。
问派派至少需要掌握多少种魔法,才能在从任意魔法阵直接传送到任意魔法阵?
方法:
在到达下一个魔法阵之前只能使用一种魔法,次数没有限制。总共有n个点对,假设我们从任意一点(, ) 到达任意另一点 (, ) 只使用一次魔法,那么就需要一个法术( - , - ),从(, ) 到达 (, )需要另一个法术,在此先不考虑,仅考虑“正向”需要的法术,对于任意不同的两点都可以求出一个这样的法术,那么在所有的法术中,有哪些是可以“抵消”的呢?因为一条法术是另一条法术的正整数倍,所以只要比值相同的法术就一定可以用一条“最简比值法术”代替,比如(3,6)和(4,8)虽然他们两个不是倍数关系,但是却可以用“最简比值法术”把他们抵消掉,因此我们的任务就是求比值相同的法术有多少条。前面说先不考虑反向的法术,现在开始考虑,会发现,虽然反向的法术与正向的法术比值相同,但是无法被抵消,因为无法使用负整数次法术,所以只需要考虑正向的然后输出结果的二倍就行了。
代码
#include <iostream> #include <algorithm> #include <cstring> #include <vector> #define endl '\n' using namespace std; typedef pair<int, int> PII; const int N = 510; vector<double> v; PII p[N]; int n; int main() { cin >> n; for(int i = 0; i <n; i++) cin >> p[i].first >> p[i].second; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(i != j) { if(p[i].first == p[j].first) //即出现了魔法为(0, x)的情况,可以全部用(0, 1)表示, v.push_back(1e9); // 用1e9 表示比值避免冲突 else v.push_back(1.0 * (p[j].second - p[i].second)/(p[j].first - p[i].first)); } } } sort(v.begin(), v.end()); v.erase(v.begin(), unique(v.begin(), v.end())); cout << v.size() * 2 << endl; return 0; }
本文作者:伍六柒-
本文链接:https://www.cnblogs.com/paper-plane/p/15991120.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步