2차원 좌표 평면상에 현빈이와 수연이가 살고 있다. 현빈이와 수연이는 통화를 자주 하는데, 둘 다 오래된 핸드폰을 쓰기 때문에 통화가 자주 끊긴다. 둘은 이리저리 자리를 옮기며 통화하던 중, 둘의 위치를 잇는 직선의 기울기가
라면 통화가 끊기지 않는다는 사실을 발견했다.
현빈이와 수연이가 있을 수 있는
개의 2차원 좌표가 주어질 때, 통화가 끊기지 않도록 현빈이와 수연이를 배치하는 경우의 수를 구해주자.
첫째 줄에는
과 가 공백으로 구분되어 주어진다.
둘째 줄부터
개 줄에 걸쳐 번 점의 좌표와 좌표가 공백으로 구분되어 주어진다.
같은 좌표는 두 번 이상 입력되지 않으며, 입력으로 주어지는 모든 값은 정수다.
통화가 끊기지 않도록 현빈이와 수연이를 배치하는 경우의 수를 구하여 출력하시오.
N이 최대 200,000이므로, O으로는 시간초과에 당할 수밖에 없습니다. 따라서 어떤 두 점을 비교하여 기울기를 대조하는 방법으로는 풀 수 없습니다. O보다 더 빠른 어떤 방법을 찾아야 하는데..
따라서, 입력받는 점 를 그대로 저장하기보다, 아래와 같은 방법을 사용하기로 합니다.
기울기가 인 임의의 점 에 대한 직선의 방정식은, 이 직선이 상수 에 대해 를 지난다고 가정할 때 다음과 같이 쓸 수 있습니다 :
이를 에 대하여 정리하면,
"두 점 를 잇는 직선의 기울기가 K" 라고 함은 직선의 방정식으로 나타내면 동일한 방정식을 가진다는 뜻이며, 이는 곧 b의 값이 같음을 의미합니다.
따라서, 입력으로 들어온 임의의 점 에 대해 의 값으로 바꾸어 이것을 key값으로, 해당 key값의 등장 횟수를 value로 하여 map 자료구조에 저장하도록 합니다.
그 후 입력이 끝나면, 각 key들의 value에 대해, 해당 value에서 2자리를 뽑는 경우의 수를 결과에 더해주도록 합니다.
어떤 key값 (위에서 말한 값)에 대한 value를 로 두면, 이 개의 자리 중에서 현빈이와 수연이를 배치하는 경우의 수는
과 같습니다.
이제 문제를 풀 준비가 다 끝났는데, 주의할 점은
따라서 map의 key와 결과인 cnt는 long long으로 선언합니다.
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#define INF 2147483647
using namespace std;
map<long long, int>points;
int main () {
ios_base::sync_with_stdio(false);
cin.tie(0);
int n;
int k;
cin >> n >> k;
for(int i=0;i<n;i++) {
int x, y;
cin >> x >> y;
points[y-(long long)k*x]++;
}
long long cnt = 0;
for(auto it = points.begin(); it != points.end(); it++) {
cnt += (long long)(it->second)*(it->second - 1);
}
cout << cnt;
}
많은 도움이 되었습니다, 감사합니다.