完美解法的两道题
来源:互联网 发布:mysql 多字段排序 编辑:程序博客网 时间:2024/06/06 00:12
近些天看到了两道题,也做了,不断修改和完善,觉得自己这两道题的解法是最优的,不知你们同意不,如果还有更好的解法,请在评论区留言.
第一题:N点共圆
题目:
给你N个整数点,判断这N个是否可能在同一个圆周上.
输入:
多组输入,第一行输入一个整数N(1<=N<=9),第二行输入2N个整数,表示N个(x,y)的点,-20 <=x,y<=20.而且给出点是逆时针给出,任意三点不共线。
输出:
如果N个点可能在同一个圆上,输出”Yes”,否则输出”No”.
样例输入:
3
000340
2
1010101
样例输出:
Yes
Yes
解析:
直接解法:浮点数模拟,先利用三点求出圆心坐标和半径,再判断其余的点时候在圆上,可以通过这个题,但是误差比较大,浮点数模拟必然会出现误差.大家普遍都是这个解法。
完美解法:由于给出的点是整点,且逆时针给出,那么我们就要想办法规避浮点数的误差,先选出三个点,因为三点确定一个圆,遍历其余的点,利用圆内四边形的判定定理:托勒密定理,判断这四个点组成的四边形是否为圆内四边形,如果其余的点与先前选出的三个点都可以组成圆内四边形,那么这N个点就在同一个圆上;判定条件:AB¯¯¯¯¯×CD¯¯¯¯¯+AD¯¯¯¯¯×BC¯¯¯¯¯==AC¯¯¯¯¯×BD¯¯¯¯¯
两边同时平方得到:AB¯¯¯¯¯2×CD¯¯¯¯¯2+AD¯¯¯¯¯2×BC¯¯¯¯¯2+2×AB¯¯¯¯¯×CD¯¯¯¯¯×AD¯¯¯¯¯×BC¯¯¯¯¯==AC¯¯¯¯¯2×BD¯¯¯¯¯2
移项再同时平方得到:(AB¯¯¯¯¯2×CD¯¯¯¯¯2+AD¯¯¯¯¯2×BC¯¯¯¯¯2−AC¯¯¯¯¯2×BD¯¯¯¯¯2)2==4×AB¯¯¯¯¯2×CD¯¯¯¯¯2×AD¯¯¯¯¯2×BC¯¯¯¯¯2
这样子,开根号的浮点运算也避免了,用这个等式可以完美判断.
代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;struct Point { LL x, y;};LL pow2(LL x){ return x * x;}LL dis2(Point a, Point b){ return pow2(a.x - b.x) + pow2(a.y - b.y);}int main(){ int n; while (cin >> n) { vector<Point> points(n); for (int i = 0; i < n; i++) cin >> points[i].x >> points[i].y; if (n < 4) { cout << "Yes" << endl; continue; } bool f = true; for (int i = 3; i < n; i++) { if (pow2(dis2(points[0], points[1]) * dis2(points[2], points[i]) + dis2(points[1], points[2]) * dis2(points[0], points[i]) - dis2(points[1], points[i]) * dis2(points[0], points[2])) != 4 * dis2(points[0], points[1]) * dis2(points[2], points[i]) * dis2(points[1], points[2]) * dis2(points[0], points[i])) { f = false; break; } } cout << (f ? "Yes" : "No") << endl; }}
第二题:股神
题目:
这是赛码网上的一个题,有人问我,我就做了下,题目链接:[点这里].
解析:
普通解法我就不赘述了,很好搞,模拟就是了.
完美解法:首先我们观察下哪一天会下降:
1−2↑3↓4↑5↑6↓7↑8↑9↑10↓⋯⋯bk↓⋯⋯
我们挑出下降的日子:3 6 10 ⋯ bk ⋯ ,b1=3 ,那么这些下降的日子是否满足通项公式呢,满足的:bk=bk−1+k+1 ,通过迭代可以求出:bk=(k+4)∗(k−1)2+3
给出某一天n ,我们可以求出最靠近n 的下降日子,这里可以通过遍历,也可以通过二分来求,遍历求法复杂度为O(n√) ,二分复杂度为O(log2n) ,待会分别给出代码;求出了
k ,那么bk 天的数字我们就知道了:abk=1+(1+2+⋯+k)−k=1+(k+1)∗k2−k
那么,在剩下的日子里,只会上涨,不会下降,因此:ans=abk+n−bk
因此,完美解法的时间复杂度为O(log2n) .
代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;int main(){ LL n; while (cin >> n) { LL x = 0, y = n; while (x < y) { LL mid = (x + y + 1) / 2; (mid + 4) * (mid - 1) / 2 + 3 <= n ? x = mid : y = mid - 1; } LL ans = 1 + (x + 1) * x / 2 - x; LL res = n - (x + 3) * x / 2 - 1; ans += res; cout << ans << endl; }}
#include <bits/stdc++.h>using namespace std;typedef long long LL;int main(){ LL n; while (cin >> n) { LL x = 0; for (; (x + 4) * (x - 1) / 2 + 3 <= n; x++); --x; LL ans = 1 + (x + 1) * x / 2 - x; LL res = n - (x + 3) * x / 2 - 1; ans += res; cout << ans << endl; }}
阅读全文
1 0
- 完美解法的两道题
- 南邮ACM 1007 完美立方 JAVA解法
- 有关数论的两道题的解法
- 判断网页编码的五种解法(这些都不是最完美的,那个研究中...)
- POJ2965的枚举解法和高效解法
- 迷宫解法之栈/队列的解法
- josephus问题的解法
- 木马病毒的通用解法
- 木马病毒的通用解法
- 木马病毒的通用解法
- 木马病毒的通用解法
- 八皇后的解法
- Ackerman 函数的解法
- 汉诺塔的递归解法
- Knight Moves 的解法
- 最大公约数的递归解法
- 九连环的解法
- 约瑟夫问题的解法
- 附录 Netty参数配置表
- Python Numpy 入门
- 关于C#中Lambda和'函数指针'的简单认识
- git 配置SSH error: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
- Linux 习题5
- 完美解法的两道题
- Linux 4.3 特性汇总
- 爬取当当网图书图片
- HTTP状态码->HTTP Status Code
- Kafka之——安装并(单节点)配置启动Kafka
- H2.64中I帧和IDR帧的区别(转)
- Linux 4.13 特性汇总
- Canvas弹幕实现
- 树莓派在ssh中添加root用户