반응형

문제 링크

 

1019번: 책 페이지

첫째 줄에 0이 총 몇 번 나오는지, 1이 총 몇 번 나오는지, ..., 9가 총 몇 번 나오는지를 출력한다.

www.acmicpc.net

 

오답 ) 완전탐색

  처음에는 완전탐색을 이용해서 풀었다.

  하지만 완전 탐색을 할 경우 최대 입력인 10억이 입력값으로 들어오는 경우

  반복문을 10억번 돌고, 또 안에서 숫자의 길이에 따라 반복문을 돌기 때문에 시간초과가 나게된다.

 

#include <cstdio>
#include <string.h>
using namespace std;

int main(void)
{
	int n, i, j, tmp, cnt[10] = {0};

	scanf("%d", &n);
	for(i = 1; i <= n; i++){
		char buf[11] = "";
		sprintf(buf, "%d", i);
		for(j = 0; j < strlen(buf); j++)
			cnt[buf[j]-'0']++;
	}
	for(i = 0; i < 10; i++)
		printf("%d ", cnt[i]);
	return 0;
}

 

  정답 ) 시간 문제를 해결하기 위해서 숫자에 따라 규칙성을 찾았다.

    0을 시작으로해서 9까지 각 숫자가 1의 자리에서 쓰일 때, 10의 자리에서 쓰일 때, ..., 각각 나누어서 더해주었다.

 

  225를 예로 2가 쓰이는 횟수를 세어보면 다음과 같다.

  1. j = 0 (1의 자리에서 쓰이는 2의 개수)

    cnt[2] += 225 / 10 * 1 (=22) : 2, 12, 22, ..., 212

    if 225 / 1 % 10 (1의 자리 수) > 2 -> cnt[2] += 1 : 222

    j = 1 (10의 자리에서 쓰이는 2의 개수)

    cnt[2] += 225 / 100 * 10 (=20) : 20~29, 120~129

    if 225 / 10 % 10 (10의 자리 수) == 2 -> cnt[2] += 225 % 10 + 1 (=6) : 220~225

    j = 2 (100의 자리에서 쓰이는 2의 개수)

    cnt[2] += 225 / 1000 * 100 (=0)

    if 225 / 100 % 10 (100의 자리 수) == 2 -> cnt[2] += 225 % 100 + 1 (=26) : 200 ~ 225

#include <cstdio>
#include <cmath>	// pow()
using namespace std;

int main(void)
{
  int n, len = 1, cnt[10] = {0, };
  scanf("%d", &n);
  int tmp = n;
  while(tmp/=10)
    len++;
  for(int i = 0; i < 10; ++i)
    for(int j = 0; j < len; ++j){
      double tmpd1 = pow(10.0, (double)j);
      double tmpd2 = pow(10.0, (double)(j+1));
      int tmp1 = (int)tmpd1;
      int tmp2 = (int)tmpd2;
      int tmp = n/tmp1%10;

      cnt[i] += (n/tmp2-(i==0?1:0)) * tmp1;
      if(tmp == i)
        cnt[i] += n%tmp1+1;
      else if(tmp > i)
        cnt[i] += tmp1;
    }
  for(int i = 0; i < 10; ++i)
    printf("%d ", cnt[i]);
  return 0;
}

 

주의점 )

  - 0의 쓰임을 확인할 때 주의해야한다.

    위의 예에서 2같은 경우 10의 자리를 확인할 때 20~29, 120~129를 확인했지만

    0의 경우 두자리인 00~09는 불가능하기 때문에 코드에서 처음 cnt[i]에 더해줄 때 0인지 확인하는 조건을 추가했다.

  - pow( ) 의 경우 반환형이 double이기 때문에 바로 사용했을 때 문제가 발생할 수 있다.

    (int)pow(10, 2)를 출력했을 때 99가 나오는 등 값이 정확하지 않아서 코드에서 다소 지저분하게 처리했다.

반응형

'문제풀이 > 백준' 카테고리의 다른 글

[C++] 백준 - 10451 : 순열 사이클  (0) 2020.03.22
[C++] 백준 - 1157 : 단어 공부  (0) 2020.03.22
[C++] 백준 - 1966 : 프린터 큐  (0) 2020.03.20
[C++] 백준 - 2164 : 카드2  (0) 2020.03.20
[C++] 백준 - 10845 : 큐  (0) 2020.03.20
반응형

문제 링크

 

1476번: 날짜 계산

준규가 사는 나라는 우리가 사용하는 연도와 다른 방식을 이용한다. 준규가 사는 나라에서는 수 3개를 이용해서 연도를 나타낸다. 각각의 수는 지구, 태양, 그리고 달을 나타낸다. 지구를 나타내는 수를 E, 태양을 나타내는 수를 S, 달을 나타내는 수를 M이라고 했을 때, 이 세 수는 서로 다른 범위를 가진다. (1 ≤ E ≤ 15, 1 ≤ S ≤ 28, 1 ≤ M ≤ 19) 우리가 알고있는 1년은 준규가 살고있는 나라에서는 1 1 1로 나타낼 수 있다. 1

www.acmicpc.net

 

풀이 ) 완전 탐색

 

  서로 다른 세 수에 대해서 나머지라고 생각해서 풀면 되는 문제이다. 공배수 개념

 

#include <cstdio>
using namespace std;

int main(void)
{
    int e, s, m, ans;
    scanf("%d%d%d", &e, &s, &m);

    ans = e-1;
    while(1){
        if(ans % 28 == s-1 && ans % 19 == m-1)
            break;
        else
            ans += 15;
    }
    printf("%d\n", ans+1);
    return 0;
}

 

주의점 )

 

- 예제 입력 4는 반드시 해보기 바란다.

 

주어지는 e, s, m의 값이 0부터가 아닌 1부터 시작하기 때문에 나머지라고 생각하여 바로 모듈러 연산을 하면 안되고 답 후보에서 1을 뺀 후 출력하기 전에 1을 더해주면 된다.

반응형

+ Recent posts