-
연속된 자연수의 합 (백준 2018번 : 수들의 합 5)C++ 2021. 9. 11. 00:02
https://www.inflearn.com/course/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/dashboard
인프런 강의 듣다가 .. 뭔가 백준에 유사한 문제 있었던 것 같아서 찾다가 풀어봄. 혼자 풀은거라 강사님 풀이와는 다르니까 ㅋㅋㅋㅋㅋㅋㅋㅋ 블로그에 기록해두려고 급하게 켰다.
뭔가 규칙성이 있을 것 같아서 좀 고민해보다가 풀었다. 예를 들어 15의 경우 15 (1개의 숫자), 7+8 (2개의 숫자), 4 + 5 + 6 (3개의 숫자), 1 + 2 + 3 + 4 + 5 (5개의 숫자) 이런식으로 표현이 가능하다.
이 규칙성에 대해서 생각해보자
덧셈에 사용되는
숫자 개수규칙성 n을 덧셈식으로 나타내는 법 2 1 + 2 = 3
2 + 3 = 5
3 + 4 = 7....
3으로 시작해서 2씩 늘어남n에서 처음 숫자 3을 빼고 ÷2를 한 몫에 +1, +2
Ex ) (15 - 3) / 2 = 6이므로 7, 8
15 = 7 + 83 1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12
6으로 시작해서 3씩 늘어남n에서 처음 숫자 6을 빼고 ÷3을 한 몫에 +1, +2, +3
Ex ) (15 - 6) / 3 = 3이므로 4, 5, 6
15 = 4 + 5 + 64 1 + 2 + 3 + 4 = 10
2 + 3 + 4 + 5 = 14
3 + 4 + 5 + 6 = 18
10부터 시작해서 4씩 늘어남n에서 처음 숫자 10을 빼고 ÷4를 한 몫에 +1, +2, +3, +4
Ex ) (22 - 10) / 4 = 3이므로 4, 5, 6, 7
22 = 4 + 5 + 6 + 75 1 + 2 + 3 + 4 + 5 = 15
2 + 3 + 4 + 5 + 6 = 20
3 + 4 + 5 + 6 + 7 = 25
15부터 시작해서 5씩 늘어남n에서 처음 숫자 15를 빼고 ÷5를 한 몫에 +1, +2, +3, +4, +5
Ex ) (30 - 15) / 5 = 3이므로 4, 5, 6, 7, 8
30 = 4 + 5 + 6 + 7 + 86 1 + 2 + 3 + 4 + 5 + 6 = 21
2 + 3 + 4 + 5 + 6 + 7 = 27
3 + 4 + 5 + 6 + 7 + 8 = 33
21부터 시작해서 6씩 늘어남n에서 처음 숫자 21을 빼고 ÷6를 한 몫에 +1, +2, +3, +4, +5, +6
Ex ) (39 - 21) / 6 = 3이므로 4, 5, 6, 7, 8, 9
39 = 4 + 5 + 6 + 7 + 8 + 9표를 보면 알 수 있듯, 2개의 연속된 숫자로 만들 수 있는 가장 작은 숫자는 3이고, 2간격으로 늘어난다. 이 규칙성을 찾은 다음 덧셈식에 규칙을 적용해보면 위의 표 가장 오른쪽처럼 적용할 수 있다.
이를 코드로 구현하기 위해 일반화를 시켜보면, 아래 표와 같다.
이 때 덧셈에 사용되는 숫자의 개수별 초기값은 3, 6, 10, 15... 이런 식으로 늘어난다. (더하는 수가 1씩 증가하는 규칙이 있다. +3, +4, +5...) 그래서 코드 상에서는 standard = standard + i로 계속 갱신해주면 된다.
덧셈에 사용되는 숫자 개수 덧셈식으로 나타내기 i 입력받은 숫자 n에서 초기값 standard빼고 i로 나눈다. (ex. (15 - 3) / 2)
이 몫에 +1, +2, ... +i가 될때까지 더한다. (6 + 1, 6 + 2)
우선 아래 코드는 인프런 강의 문제를 스스로 풀어본 코드이다. 백준과 다른 점이라면, 자기 자신으로만 이루어진 것은 카운트 하지 않고, 가능한 수식을 다 출력해줘야한다. (그래서 반복문이 중첩되어 있다. )
int main() { int i, j, num, temp, count = 0, standard = 1; scanf("%d", &num); //배분할 숫자 입력받음 temp = num; //직접 num을 조작하지 않기 위해 temp에 값 복사 for(i=2; temp-standard > 0; i++) { standard += i; if((temp-standard) % i == 0) { for(j=1; j<i; j++) { //i개의 숫자의 합으로 표현하기 위해 j=i만큼 출력용 반복문 돌림. printf("%d + ", (temp-standard)/i+j); } printf("%d = %d\n", (temp-standard)/i+j, num); count++; } } printf("%d\n", count); }
변수 설명
- i : 덧셈에 사용되는 숫자 개수,
- j : +1, +2, ... +i까지 몫에다가 더하는 용. 그런데 수식을 만들어야하므로 j <=i가 아니고 j< i까지 한다음, 마지막 출력문은 빼주었다.
- count : 수식 개수
코드 설명
for(i=2; temp-standard > 0; i++) { standard += i;
-> standard가 초기값이므로 temp가 standard보다 진행 중지. 위에서 설명했듯 i는 덧셈식을 이루는 숫자 개수
-> standard += i는 각 숫자 개수 별로 초기값 갱신을 위한 코드
if((temp-standard) % i == 0) {
-> 15에서 3빼고 2로 나눴을때 나누어떨어진다 == 15를 2개의 숫자의 합으로 표현가능하다
-> 합으로 표현 가능한경우만 수식 출력하면 되므로
for(j=1; j<i; j++) { printf("%d + ", (temp-standard)/i+j); } printf("%d = %d\n", (temp-standard)/i+j, num); count++;
-> i만큼 몫으로 나온 숫자인 (temp - standard) / i에 각각 더해주면 된다.
-> j가 1부터 시작해서 1, 2, 3, ... i까지 더해줘야한다. 수식형태를 만들어야 해서 마지막 더하는 숫자는 반복문 밖으로 뺐다.
-> count를 증가시킨다.
백준 코드
#include <stdio.h> int main() { int i, j, num, temp, count = 1, standard = 1; scanf("%d", &num); temp = num; for(i=2; temp-standard > 0; i++) { standard += i; if((temp-standard) % i == 0) { count++; } } printf("%d\n", count); }
위 코드보다 많이 단순화 되었다. count만 출력하면 되기 때문...
대신 백준은 자기 자신만으로 표현하는것도 들어가서 count를 처음에 1로 초기화시켜놨다. (어떤 수든 자기 자신이 포함되니까) 그리고 수식 출력하는 부분만 다 날리면 된다.
채점 결과는 이렇게 나왔다. 기억에서 날아가기 전에 블로그에 쓴다...
'C++' 카테고리의 다른 글
백준 13458번 시험감독 (0) 2021.12.11 백준 2503번 숫자야구 (0) 2021.12.11 카카오 2018 코테 문제2 LZW 압축 문제 (C++) (0) 2021.10.02