https://www.acmicpc.net/problem/11068
11068번: 회문인 수
어떤 수를 왼쪽부터 읽어도, 오른쪽부터 읽어도 같을 때 이 수를 회문인 수라고 한다. 예를 들어, 747은 회문인 수이다. 255도 회문인 수인데, 16진수로 표현하면 FF이기 때문이다. 양의 정수를 입력
www.acmicpc.net
회문
- 펠린드롬
- 거꾸로 읽어도 똑같은 것
입력 받은 숫자를 2진법 ~ 64진법으로 표현했을 때 회문인 경우가 하나라도 있으면 1, 없으면 0을 출력하는 문제이다.
진법
- 10진법 -> B진법으로 변환하기 : (숫자를 B로 나눈 나머지 값을 맨 뒤부터 놓고, 숫자를 B로 나눈다.) 반복
(개떡같은 설명 ...)
여기서 생각할 것은 숫자를 완전히 B진법으로 바꿀 필요가 없다는 것이다.
이 문제에서는 입력 값이 최대 1,000,000이긴 하지만 더 커질 경우 B진법 수를 다 계산하면 낭비낭비
회문 -> 가운데를 기준으로 똑같은 모양이다.
그러니까 B진법으로 중간까지만 구하고, 그 다음부터는 나머지를 계산하고 바로바로 비교를 한다.
중간에 하나라도 다르면 더이상 계산할 필요 없이 break 한다.
중간까지만 구하기? 중간이 어디일까
10진수를 B진법으로 변환했을 경우의 길이는 ceiling(log_B (10진수))
8을 2진수로 나타내면 1000 => 4자리 = log2 8 + 1
로그 계산
C언어의 <math.h> 에는 밑이 2인 로그를 계산해주는 함수가 있다.
log2(num) -> double 형을 반환한다. 이 값을 int로 형변환을 해주면 알아서 뒤에는 버려지니까 + 1 해주면 된다.
공식 긴가민가해서 검색해봄..; 하튼 이렇게 변환해서 구하면 된다.
코드
B진법으로 변환한 숫자를 저장할 배열 num_in_b는 [20]으로 선언했는데 문제에서 최댓값 1,000,000이고 2진수로 나타냈을 때 20자리 정도여러 이렇게 잡았다. 근데 어차피 반만 쓸거라서 [20]까지 필요 없다.
int num;
scanf("%d", &num);
int num_in_b[20]; //B진법으로 나타낸 값을 저장할 배열
int rst;//회문이면 TRUE
// B의 값의 범위 2 ~ 64
for(int b = 2; b <= 1<<6; b++) {
rst = TRUE;
int temp = num;
//B진법 자릿수 검사
int len = (int)(log2(temp)/log2(b)) + 1;
for(int r = 0; r < len/2; r++) {
num_in_b[r] = temp % b;
temp /= b;
}
// 길이가 홀수인 경우 나눠주되, 기록은 하지 않음
if((len&1) != 0) temp /= b;
// 채워진 배열의 뒷부분부터 같은지 검사한다.
for(int s = len/2 -1; s >= 0; s--, temp /= b) {
// 하나라도 다르면 현재 B는 FALSE
if(num_in_b[s] != temp % b){
rst = FALSE;
break;
}
}
if(rst) {
break;
}
}
printf("%d\n", (rst)? 1:0);
'Algorithms' 카테고리의 다른 글
[BOJ 9028: Iris] 구현, 문자열 | C언어 (3) | 2023.10.13 |
---|---|
[Greedy Algorithm] 그리디 알고리즘 - 정당성 증명은 필수 (0) | 2023.07.15 |
알고리즘 문제 풀 때 Runtime Error 발생시 (0) | 2023.07.15 |
[알고리즘] (0) | 2023.07.15 |