B. Arpa and an exam about geometry
传送门:http://codeforces.com/contest/851/problem/B
本题是一个平面几何问题。
平面上有3个点A,B,C,坐标分别为(ax,ay),(bx,by),(cx,cy)。现以平面上一点P为中心,将点A,B,C旋转角度θ,旋转后的点分别为A’,B’,C’。试问:是否存在点P和角度θ,使得“点A’与点B重合,点B’与点C重合”?
以上条件等价于:存在点P和角度θ,使得“|PA|=|PB|=|PC|,且∠APB=∠BPC=θ”。
考虑点A,B,C的几何关系:
若A,B,C位于同一条直线上,则不存在满足条件的点P和角度θ;
若A,B,C不位于同一条直线上,若存在满足条件的点P和角度θ,则由等价条件可知:△APB≌△BPC,因此|AB|=|BC|。
因此,题中条件成立,当且仅当“A,B,C不共线,且|AB|=|BC|”。
A,B,C三点共线的一个充分条件是直线AB与BC的斜率相等,但这是一个充分不必要条件。
A,B,C三点共线的一个充分必要条件可以通过向量形式给出:
向量α1=(Δx1,Δy1)T,α2=(Δx2,Δy2)T,其中Δx1=bx-ax,Δy1=by-ay,Δx2=cx-bx,Δy2=cy-by。
若向量α1与α2共线,则向量组α1,α2线性相关。设A=(α1,α2),则detA=0。
$$det A=left|egin{matrix}Delta x_1&Delta x_2\Delta y_1&Delta y_2end{matrix} ight|=0LeftrightarrowDelta x_1cdotDelta y_2=Delta x_2cdotDelta y_1$$
因此,A,B,C三点共线的一个充分必要条件是Δx1·Δy2=Δx2·Δy1。参考程序如下:
#include <stdio.h> #include <stdint.h> int main(void) { int ax, ay, bx, by, cx, cy; scanf("%d%d%d%d%d%d", &ax, &ay, &bx, &by, &cx, &cy); int64_t dx1 = bx - ax, dy1 = by - ay; int64_t dx2 = cx - bx, dy2 = cy - by; if (dx1 * dy2 == dx2 * dy1) printf("No "); else { if (dx1 * dx1 + dy1 * dy1 == dx2 * dx2 + dy2 * dy2) printf("Yes "); else printf("No "); } return 0; }
C. Five Dimensional Points
传送门:http://codeforces.com/contest/851/problem/C
本题是一个空间几何问题。
在五维空间中,有n个不同的点P1,P2,...,Pn,Pi的坐标为(ai,bi,ci,di,ei)。现有定义:点A为bad,当且仅当存在不同于点A的点B和点C,使得向量AB与AC的夹角为锐角;否则,点A为good。求{1,2,...,n}的子集S,使得对于S中的每一个元素i,均有Pi为good。
向量的夹角按照以下公式计算:$<oldsymbol{a},oldsymbol{b}>=arccos frac{oldsymbol{a}cdot oldsymbol{b}}{|oldsymbol{a}||oldsymbol{b}|}$
而对于向量a=(a1,a2,...,ak),b=(b1,b2,...,bk),内积a·b的计算公式为: $oldsymbol{a}cdotoldsymbol{b}=sum_{j=1}^{k}{a_{j}b_{j}}$
本题直接模拟即可,时间复杂度为O(n3)。
参考程序如下:
#include <stdio.h> #include <stdbool.h> #define MAX_N 1000 typedef int quint[5]; quint p[MAX_N], v[MAX_N][MAX_N]; int good[MAX_N]; int main(void) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { for (int k = 0; k < 5; k++) { scanf("%d", &p[i][k]); } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < 5; k++) { v[i][j][k] = p[j][k] - p[i][k]; } } } int cnt = 0; for (int t = 0; t < n; t++) { bool flag = false; for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { int inp = 0; for (int k = 0; k < 5; k++) { inp += v[t][i][k] * v[t][j][k]; } if (inp > 0) { flag = true; break; } } } if (!flag) { good[cnt++] = t + 1; } } printf("%d ", cnt); for (int i = 0; i < cnt; i++) { printf("%d ", good[i]); } return 0; }