본문 바로가기

코테문제

[백준] B11170

https://www.acmicpc.net/problem/11170

 

11170번: 0의 개수

N부터 M까지의 수들을 종이에 적었을 때 종이에 적힌 0들을 세는 프로그램을 작성하라. 예를 들어, N, M이 각각 0, 10일 때 0을 세면 0에 하나, 10에 하나가 있으므로 답은 2이다.

www.acmicpc.net

# 아이디어

n부터 m까지의 숫자의 0의 개수를 찾자. (0 <= n <= m <= 1,000,000)

단순히 m과 n사이의 0의 수를 계산하려면 어렵다. 따라서, m까지의 0의 수 - n까지의 0의 수로 출력값을 계산하자.

만약 n이 0을 포함하는 값이면 출력 결과를 계산할 때 n의 0의 개수만큼 더해주면 된다.

만약 m이 0을 포함하지 않는 값이면 가장 가까운 0을 가지는 작은 값으로 변환하여 계산한다.

 

=> 규칙 구하기

한 자릿수 = 1 -> 1

0,1,2,3,4,5,6,7,8,9

두 자릿수 = 9* 1 -> 9

10,11,12,13,14,15,16,17,18,19

20,21,22,23,24,25,26,27,28,29

...

90,91,92,93,94,95,96,97,98,99

세 자릿수 = 9* ( (2+1*9) + 1*9) ) -> 180

100,101,102,103,104,105,106,107,108,109

110,111,112,113,114,115,116,117,118,119

120,121,122,123,124,125,126,127,128,129

...

190,191,192,193,194,195,196,197,198,199

 

200,201,202,203,204,205,206,207,208,209

210

220

290

네 자릿수 = 9* ( {1* (3+2*9 + 9*(2+1*9))} + {9* ((2+1*9) + 1*9)} ) -> 2052

1000,1001,1002,1003,1004,1005,1006,1007,1008,1009

1010,1011,1012,1013,1014,1015,1016,1017,1018,1019

1020

...

1090

1100,1101,1102,1103,1104,1105,1106,1107,1108,1109

1110,1111,1112,1113,1114,1115,1116,1117,1118,1119

1120

...

1190,...,1199

1200

1900

 

2000

다섯 자릿수 = 9* (31 + 21*9) + 9*2052

10000,10001,10002,10003,10004,10005,10006,10007,10008,10009

10010,10011,10012,10013,10014,10015,10016,10017,10018,10019

10020

10090

10100,10101,

...

11000,11001,

11010

 

20000

※ 0의 개수 규칙:

11, 21, 31, 41, ... 순으로 첫번째 줄의 0의 개수이다.

자릿수 하나가 늘어난 0의 개수는 1개의 새로운 값과 9개의 이전의 값을 더하면 된다. (세 자릿수 이상일 때)

 

### 블로그 참조 (규칙 도저히 못찾겠다;;;;)

n과 m의 범위가 다음과 같기 때문에 일일히 직접 계산해준다. (0 <= n <= m <= 1,000,000)

 

	public static int countZero(int start, int last) {
		int cnt = 0;
		for (int i = start; i <= last; i++) {
			int current = i;
			if (current == 0)
				cnt++;

			while (current >= 1) {
				if (current % 10 == 0) {
					cnt++;
				}
				current /= 10;
			}
		}

		return cnt;
	}

항상 일의 자리만 보고 0인지 아닌지 판별하여 cnt를 늘려주고

이후에 10으로 나눈값을 다시 반복적으로 판별한다.

current에서 가장 높은 자릿수를 판별한 뒤 10으로 나누면 항상 그 값은 0이기 때문에 while문을 탈출한다.

 

💢💢💢

10으로 /연산하고 *연산으로 13 -> 10, 29->20으로 만들어 10과 20까지의 0의 개수를 구하자는 생각을 했었는데, 정작 0의 개수를 어떻게 구할지는 생각을 하지 않았다. 0의 개수가 나타나는 규칙을 찾는 생각에 매몰되어 생각을 넓게 하지 못했다.

 

# 오답

- 런타임 에러 발생

	public static int countZero(int start, int last) {
		int cnt = 0;
		for (int i = start; i <= last; i++) {
			int current = i;
			if (current == 0)
				cnt++;

			while (current >= 1) {
				if (current % 10 == 0) {
					cnt++;
				}
				current /= 10;
			}
		}

		return cnt;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int testCase = sc.nextInt();
		int[] n = new int[3];
		int[] m = new int[3];
		int[] cnt = { 0, 0, 0 };

		for (int i = 0; i < testCase; i++) {
			n[i] = sc.nextInt();
			m[i] = sc.nextInt();

			cnt[i] = countZero(n[i], m[i]);
		}

		for (int i = 0; i < cnt.length; i++) {
			System.out.println(cnt[i]);
		}

		sc.close();

	}

 

Sol1.

Scanner에서 BufferedReader, StringBuilder 사용하는 것으로 변경

package baekjoon;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class B11170 {

	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int testCase = Integer.parseInt(br.readLine());
		
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < testCase; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int n = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());

			int cnt = 0;
			for (int j = n; j <= m; j++) {
				int current = j;
				if (current == 0)
					cnt++;

				while (current >= 1) {
					if (current % 10 == 0) {
						cnt++;
					}
					current /= 10;
				}
			}
			sb.append(cnt).append("\n");
		}
		System.out.println(sb);

	}

}

 

💯💯💯

StringBuilder를 사용하여 .append("\n")를 이용하면 여러가지 값을 하나로 묶어서 출력할 수 있다.

=> 배열 메모리 낭비와 for문 반복을 줄일 수 있다.

'코테문제' 카테고리의 다른 글

[백준] S1260  (0) 2023.11.05
[백준] S16173  (0) 2023.10.31
[백준] B2460  (0) 2023.09.29
[백준] S17276 미완성  (0) 2023.09.27
[백준] S1913  (0) 2023.09.24