2차원배열 가장 왼쪽 위부터 시작하는 table이 있다. 이table은 다음과같은 패턴으로 순서대로 생성이 된다. 위와같은 패턴으로 table이 무한정 생성될 때 k가 존재하는 행과 열을 구하여라.
피드백
Input
1-st line : Testcase (1 <= t <= 100) 각 Testcase 마다 t-th line : 1개의 정수 (1 <= k <= 109)
Output
각 Testcase 마다 2개의 정수 (r, c >= 1) space로 구분 : k가 위치하고있는 열과 행
문제 풀이
또 800점 문제이다. 또한 패턴만 구하면 간단하게 해결할 수 있었다.
0번째 열을 확인해보면 각각 n번째 행의 원소들이 n의 제곱인것을 확인할 수 있다. 다르게 말하면 0번째 행의 0보다 큰 n번째 열의 원소는 n-1의 제곱 + 1이라는 사실도 성립된다. 또한 변화하는 행과 열의 종류가 변경되는 시점은 n-1의 제곱 + (n-1)이기 때문에 k의 위치는 쉽게 구할 수 있었다.
최종 해설
먼저 정수형 sq를 선언하여 k의 제곱근(소수점부분은 제외)을 구하였다.
만약 소수점을 제외한 sq의 제곱이 k와 같다면, k의 위치는 0열 sq행으로 고정되기 때문에 예외를 두어 처리를 해 주었다.
다음으로 알아야 하는것은 k가 위치하고 있는 곳이 열이 변경되는 구간인지, 행이 변경되는 구간인지 알 필요가 있다. 먼저 행과 열이 바뀌는 구간은 sq의 제곱 + sq로 구할 수 있다. (행과 열이 만나는 시점)
따라서 해당 값보다 크게 되면, 가로로 배치되는 시점이므로 행의 위치는 sq+1로 고정이며 열의 위치는 sq+1의 제곱에서 k값을 뺀 값이 k가 위치하는 열의 번호가 된다.
또는
행과 열이 만나는 시점보다 k의 값이 작게 되면, 세로로 배치되는 시점이므로 열의 위치는 sq+1로 고정이며 행의 위치는 k에서 sq의 제곱을 뺀 값이 된다.
원형의 식탁에서 회의를 하는데 인원은 모르고(짝수이다) 모든 사람은 서로 마주보는 상대가 있다. 각자의 번호는 1부터 시작해서 시계방향으로 숫자를 매긴다. a 와 b가 마주보고 있을 때, c와 마주보고 있는 사람의 번호를 구하여라.
피드백
Input
1-st line : Testcase (1 <= t <= 104) 각 Testcase 마다 t-th line : space로 구분된 3개의 정수 (1 <= a, b, c <= 108)
Output
각 Testcase 마다 1개의 정수 d : c와 마주보고있는 숫자 답이 여러개일시 아무거나 출력, 답이 없으면 -1출력
문제 풀이
이문제 또한 어려운 문제는 아니였다. 규칙만 잘 찾으면 되는 문제였지만, 예상외로 해맸었다.
Attr 1 (Time Limit exceeded on test 2)
첫시도부터 굉장히 복잡하게 생각을 했는데 일단 무조건 규칙이 있을것이라고 예상을 하였다. 그래서 열심히 규칙을 찾아본 결과.. 서로 마주보는 a와 b를 기준으로 a-n은 b-n을 마주보고 있다는 사실을 알게 되었다. 또한 계속 빼가다가 어느 한 수가 0에 도달하게 되면, 큰수 + (큰수 - n - 작은수)가 원탁에 앉아있는 총 인원 수가 나왔다. 복잡하다 또는 큰수-n과 작은수의 값이 같아지면, 큰수 + (작은수 - n) 의 값이 총 인원수가 되었다.
결국 for문으로 돌려서 위 두 케이스중 하나의 케이스가 나오게 되면 Loop를 빠져나가고 남은 값들을 계산하여 값을 도출해 냈다. 물론 결과는
#include<iostream> #include<algorithm> usingnamespace std; intmain(void){ int TestCase = 0; cin >> TestCase; while (TestCase --) { int a, b, c; cin >> a >> b >> c; int big = max(a, b); int small = min(a, b); int i, meet = small - 1; int result = -1; for (i = big-1; i > small && meet > 0; i--, meet--) { if (result == -1) { if(i == c) result = meet; elseif(meet == c) result = i; } } //cout << "i = " << i << ", m = " << meet << endl; if(result == -1 && i > small && meet == 0) { if(c > small && c <= i) result = big + (c-small); elseif(c > big && c <= (big + (i-small))) result = small + (c-big); } cout << result << endl; } return0; }
Attr 2 (Wrong answer on test 2)
시간초과로 한대 맞고난 뒤 for문으로 해결할 수 없는 문제라는 사실을 문제를 본지 40분만에 알아차렸다. 결국 다른 규칙을 찾다가 한가지 핵심적인 규칙을 깨닳을 수 있었다.
서로 마주보고있는 두 수의 간격은 무조건 전체 인원수의 절반이 된다. 이 규칙을 찾은 후 이 규칙을 가지고 코드를 짰다. 기본적으로 두 수의 간격을 구하고, 그 간격을 기준으로 c값이 작으면 전체 인원수의 절반을 더해주고, c값이 크면 전체 인원수의 절반을 빼주는 형식으로 정답을 구했다. 또한 몇가지의 예외사항을 넣어두었다.
앞에서 했던 for문 뻘짓을 왜했는지 이해가 되지 않았지만 8분만에 코드를 짜고 제출을 하였다. 그러나 결과는
intmain(void){ int TestCase = 0; cin >> TestCase; while (TestCase --) { int a, b, c, result = -1; cin >> a >> b >> c; int big = max(a, b); int small = min(a, b); int dis = big - small; if(c > dis) result = c-dis; elseif (c <= dis) result = c + dis; if(result > dis*2 || big > dis*2) result = -1; cout << result << endl; } return0; }
Attr 3 (Accepted!)
결국 또하나의 예외를 찾아내고 나서야 문제를 해결할 수 있었다.
“c가 전체 인원수보다 크면: a와 b가 마주보고 있는 원탁에는 c는 존재할 수 없다.” 결론적으로 이 예외조건을 추가하니 정상적으로 코드가 Accept 되었다.
최종 해설
서로 마주보고있는 두 수의 간격은 무조건 전체 인원수의 절반이 된다.
a와 b를 사용하여 전체 인원수의 절반을 구하고, 그 수를 기준으로 하여 c에 따라서 결과값을 구해주면 된다. 규칙만 잘찾으면 어렵지않게 풀 수 있는 문제였다. 괜히 반복문으로 접근해서 시간만 날렸다
?c가 전체 인원수의 절반보다 작거나 같으면: 정답 : c + 전체 인원수의 절반;
?아니면 c가 전체 인원수의 절반보다 크면: 정답 : c - 전체 인원수의 절반;
만약: 정답이 전체 인원수보다 크면: 정답 : -1; 제대로된 원탁이 아니다.
또는: c가 전체 인원수보다 크면: 정답 : -1; a와 b가 마주보고 있는 원탁에는 c는 존재할 수 없다.
또는: a와 b중에 큰 수가 전체 인원수보다 크면: 정답 : -1; a와 b중에 큰 수는 제대로된 원탁에 존재할 수 없다.
#include<iostream> #include<algorithm> usingnamespace std; intmain(void){ int TestCase = 0; cin >> TestCase; while (TestCase --) { int a, b, c, result = -1; cin >> a >> b >> c; int big = max(a, b); int small = min(a, b); //총 인원수의 절반 int dis = big - small; if(c > dis) result = c-dis; elseif (c <= dis) result = c + dis; //답이 나오지 않는 경우 if(result > dis*2 || big > dis*2 || c > dis*2) result = -1; cout << result << endl; } return0; }
느낀점
원형탁자 -> 숫자 -> 순서대로 -> 반복문!! 일것이라고 안일하개 생각한게 문제가 되었다. 결국 초반에 반복문으로 계속 고민을 하다가 시간만 날려버리게 되었다. 문제를 해결하는 방법에 편견을 가지지 말고 다양한 방법을 생각해 봐야할 것 같다.