728x90

문제

문장이 주어졌을 때, 단어를 모두 뒤집어서 출력하는 프로그램을 작성하시오. 단, 단어의 순서는 바꿀 수 없다. 단어는 영어 알파벳으로만 이루어져 있다.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 문장이 하나 주어진다. 단어의 길이는 최대 20, 문장의 길이는 최대 1000이다. 단어와 단어 사이에는 공백이 하나 있다.

출력

각 테스트 케이스에 대해서, 입력으로 주어진 문장의 단어를 모두 뒤집어 출력한다.

코드 1

import sys
t = int(sys.stdin.readline())
#스택
for i in range(t):
    string = sys.stdin.readline().rstrip()
    string += " "

    stack = []
    for j in string:
        if j != " ":
            stack.append(j)
        else:
            while stack:
                print(stack.pop(),end = "")
            print(' ',end="")

풀이 1

문자열을 넣고 거꾸로 출력을 하니까 스택 자료구조로 구현했다.

문자열을 스택에 넣고 " "을 만나면 pop() 한다.

주의할 점은 마지막 문자열 끝에 " "가 안 들어가니까 뒤집기가 안된다. 

그래서 마지막 문자열에도 " "을 넣어준다.

코드 2

import sys
t = int(sys.stdin.readline())

#문자열 슬라이싱
for i in range(t):
    string = sys.stdin.readline().rstrip().split()
    for str in string:
        print(str[::-1],end=" ")
    print()

풀이 2

python은 문자열을 다루기 좋은 언어이다.

python의 장점을 활용해 " "마다 잘라서 str[::-1] 을 사용해 뒤집어줬다.

728x90

문제

정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다.

  • 1+1+1+1
  • 1+1+2
  • 1+2+1
  • 2+1+1
  • 2+2
  • 1+3
  • 3+1

정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 11보다 작다.

출력

각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 출력한다.

코드

import sys
t = int(sys.stdin.readline())
def sol(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n == 3:
        return 4
    else:
        return sol(n-3) + sol(n-2) + sol(n-1)

for i in range(t):
    n = int(sys.stdin.readline())
    print(sol(n))

풀이

n이

1 일 때 1 -> 총 1가지

2일 때 1+1, 2 -> 총 2가지

3일 때 1+1+1, 1+2, 2+1, 3 -> 총 4가지

4일 때 1+1+1+1, 1+1+2, 1+2+1, 2+1+1, 1+3, 3+1, 2+2 -> 총 7가지

5일 때 1+1+1+1+1, 1+1+1+2, 1+1+2+1, 1+2+1+1, 2+1+1+1, 1+1+3, 1+3+1, 3+1+1, 2+3, 3+2, 2+2+1, 2+1+2, 1+2+2 -> 총 13가지

...

이렇게 구해보면 규칙을 찾을 수 있다.

점화식을 세워 구하면 된다.

 

f(n) = f(n-3) + f(n-2) + f(n-1) (단, n>3)

728x90

문제

N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.

출력

첫째 줄에 합이 S가 되는 부분수열의 개수를 출력한다.

코드 1

import sys
n, s = map(int,sys.stdin.readline().split())
arr = list(map(int,sys.stdin.readline().split()))

def dfs(idx,sum):
    global cnt
    if idx>=n:
        return
    sum += arr[idx]
    if sum == s:
        cnt+=1
    dfs(idx+1, sum)
    dfs(idx+1, sum-arr[idx])

cnt = 0
dfs(0,0)
print(cnt)

풀이 1

백트래킹으로 구현했다. 

완전탐색을 하면서 불필요한 탐색은 가지치기하는 방법이다.

dfs을 하면서

1. 현재 arr [idx] 을 포함하는 경우

2. 현재 arr [idx] 을 포함하지 않는 경우

경우의 수를 가지치기 한다.

 

코드 2

import sys
from itertools import combinations
n, s = map(int,sys.stdin.readline().split())
arr = list(map(int,sys.stdin.readline().split()))

#조합
cnt = 0
for i in range(1,n+1):
    comb = list(combinations(arr,i))
    for j in comb:
        if sum(j) == s:
            cnt+=1

print(cnt)

풀이 2

조합을 사용해서 크기가 1부터 n까지의 부분수열을 만들고 그 합이 s일 때 cnt+=1 한다.

728x90

문제

1742년, 독일의 아마추어 수학가 크리스티안 골드바흐는 레온하르트 오일러에게 다음과 같은 추측을 제안하는 편지를 보냈다.

4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다.

예를 들어 8은 3 + 5로 나타낼 수 있고, 3과 5는 모두 홀수인 소수이다. 또, 20 = 3 + 17 = 7 + 13, 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23 이다.

이 추측은 아직도 해결되지 않은 문제이다.

백만 이하의 모든 짝수에 대해서, 이 추측을 검증하는 프로그램을 작성하시오.

입력

입력은 하나 또는 그 이상의 테스트 케이스로 이루어져 있다. 테스트 케이스의 개수는 100,000개를 넘지 않는다.

각 테스트 케이스는 짝수 정수 n 하나로 이루어져 있다. (6 ≤ n ≤ 1000000)

입력의 마지막 줄에는 0이 하나 주어진다.

출력

각 테스트 케이스에 대해서, n = a + b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자는 공백 하나로 구분되어져 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰 것을 출력한다. 또, 두 홀수 소수의 합으로 n을 나타낼 수 없는 경우에는 "Goldbach's conjecture is wrong."을 출력한다.

코드

import sys
import math

arr = [True for _ in range(1000001)]
for i in range(2,int(math.sqrt(1000001))):
    if arr[i]:
        j = 2
        while i*j<1000001:
            arr[i*j] = 0
            j+=1

while True:
    n = int(sys.stdin.readline())
    if n == 0:
        break

    flag = 0
    for i in range(3,len(arr)):
        if arr[i]:
            if arr[n-i]:
                print(n, "=", i, "+", n-i)
                flag = 1
                break
    if flag == 0:
        print("Goldbach's conjecture is wrong.")

풀이

주워진 범위 내의 모든 소수를 구할 때는 에라토스테네스의 체 알고리즘을 사용해야 효율적이다.

하지만, 처음에 arr의 크기를 1000001 로 주지 않고 입력받은 값으로 계속 반복문을 돌아서 시간 초과가 났다..

입력값의 조건 중 테스트 케이스의 개수는 100000개를 넘지 않는다고 쓰여 있다.

이 조건을 활용해 에라토스테네스의 체로 구현하면 시간 초과를 겪지 않는다.

 

728x90

문제

선영이는 주말에 할 일이 없어서 새로운 언어 AC를 만들었다. AC는 정수 배열에 연산을 하기 위해 만든 언어이다. 이 언어에는 두 가지 함수 R(뒤집기)과 D(버리기)가 있다.

함수 R은 배열에 있는 수의 순서를 뒤집는 함수이고, D는 첫 번째 수를 버리는 함수이다. 배열이 비어있는데 D를 사용한 경우에는 에러가 발생한다.

함수는 조합해서 한 번에 사용할 수 있다. 예를 들어, "AB"는 A를 수행한 다음에 바로 이어서 B를 수행하는 함수이다. 예를 들어, "RDD"는 배열을 뒤집은 다음 처음 두 수를 버리는 함수이다.

배열의 초기값과 수행할 함수가 주어졌을 때, 최종 결과를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 최대 100이다.

각 테스트 케이스의 첫째 줄에는 수행할 함수 p가 주어진다. p의 길이는 1보다 크거나 같고, 100,000보다 작거나 같다.

다음 줄에는 배열에 들어있는 수의 개수 n이 주어진다. (0 ≤ n ≤ 100,000)

다음 줄에는 [x1,...,xn]과 같은 형태로 배열에 들어있는 정수가 주어진다. (1 ≤ xi ≤ 100)

전체 테스트 케이스에 주어지는 p의 길이의 합과 n의 합은 70만을 넘지 않는다.

출력

각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.

코드 1

import sys
from collections import deque
t = int(sys.stdin.readline())

for i in range(t):
    p = list(sys.stdin.readline().rstrip())
    n = int(sys.stdin.readline())
    arr = sys.stdin.readline()[1:-2].rstrip().split(",")

    if n ==0:
        q = deque()
    else:
        q = deque(arr)

    rev = 0
    flag = 0 #error 인지 확인

    for j in p:
        if j=="R":
            rev+=1
        elif j== "D":
            if len(q)==0:
                print("error")
                flag = 1
                break
            else:
                if rev % 2 ==0:
                    q.popleft()
                else:
                    q.pop()
    if flag == 0:
        if rev % 2 ==0:
            print("["+",".join(q)+"]")
        else:
            q.reverse()
            print("[" + ",".join(q) + "]")

풀이 1

입력을 [1,2,3,4] 이렇게 받으니, 아래와 같이 슬라이싱 해서 입력받아야 한다.

arr = sys.stdin.readline()[1:-2].rstrip().split(",")

reverse() 연산과 popleft() 연산이 필요한 것을 보아 deque 라이브러리를 사용해서 을 구현했다.

하지만 R이 나올 때마다, reverse()연산을 했더니 시간 초과가 났다.

 

생각을 더 해보면, R은 짝수이면 뒤집기를 안한 것 과 같아서 홀수 일 때만 뒤집으면 된다.

또한, R이 짝수 이면 뒤집기를 안한 것과 같으니 맨 처음의 원소를 삭제하는 popleft() 연산을 하면 되고, 

R이 홀수 이면 맨 뒤에 원소를 삭제하는 것과 같아서 pop()연산을 한다.

 

flag 변수는 error 임을 체크하는 변수로 쓰였고 최종적으로 R이 홀수 일 때만 출력 전에 reverse() 연산을 해준다.

코드 2

import sys

t = int(sys.stdin.readline())

for i in range(t):
    p = sys.stdin.readline().rstrip()
    n = int(sys.stdin.readline())
    arr = sys.stdin.readline()[1:-2].rstrip().split(",")
    p = p.replace("RR","")

    rev = 0
    f,b = 0,0
    flag = 0 #error 인지 확인

    for j in p:
        if j=="R":
            rev+=1
        elif j== "D":
            if rev % 2 ==0:
                f+=1
            else:
                b+=1
    if f+b <= n:
        arr = arr[f:n-b]
        if rev % 2 ==0:
            print("["+",".join(arr)+"]")
        else:
            print("[" + ",".join(arr[::-1]) + "]")
    else:
        print("error")

풀이 2

덱 라이브러리를 사용하지 않고 문자열 슬라이싱으로 풀이하는 방법이다.

우선, 풀이1의 방법과 비슷한 점이 있다.

R이 짝수면 앞에서부터 제거 (f+=1 표시)

R이 홀수면 뒤에서부터 제거 (b+=1 표시)

그리고 RR이 연속해 있으면 ""으로 교체해 제거한다.

 

f+b의 합이 n보다 크면 error 출력하고

이하이면 문자열을 f부터 n-b까지 저장하고 reverse 연산을 한다.

 

python에서는 리스트를 뒤집는 방법이 reverse()연산 말고도

list[::-1] 방법이 있다.

728x90

문제

직선으로 되어있는 도로의 한 편에 가로수가 임의의 간격으로 심어져있다. KOI 시에서는 가로수들이 모두 같은 간격이 되도록 가로수를 추가로 심는 사업을 추진하고 있다. KOI 시에서는 예산문제로 가능한 한 가장 적은 수의 나무를 심고 싶다.

편의상 가로수의 위치는 기준점으로 부터 떨어져 있는 거리로 표현되며, 가로수의 위치는 모두 양의 정수이다.

예를 들어, 가로수가 (1, 3, 7, 13)의 위치에 있다면 (5, 9, 11)의 위치에 가로수를 더 심으면 모든 가로수들의 간격이 같게 된다. 또한, 가로수가 (2, 6, 12, 18)에 있다면 (4, 8, 10, 14, 16)에 가로수를 더 심어야 한다.

심어져 있는 가로수의 위치가 주어질 때, 모든 가로수가 같은 간격이 되도록 새로 심어야 하는 가로수의 최소수를 구하는 프로그램을 작성하라. 단, 추가되는 나무는 기존의 나무들 사이에만 심을 수 있다.

입력

첫째 줄에는 이미 심어져 있는 가로수의 수를 나타내는 하나의 정수 N이 주어진다(3 ≤ N ≤ 100,000). 둘째 줄부터 N개의 줄에는 각 줄마다 심어져 있는 가로수의 위치가 양의 정수로 주어지며, 가로수의 위치를 나타내는 정수는 1,000,000,000 이하이다. 가로수의 위치를 나타내는 정수는 모두 다르다.

출력

모든 가로수가 같은 간격이 되도록 새로 심어야 하는 가로수의 최소수를 첫 번째 줄에 출력한다.

코드

import math
import sys
n = int(sys.stdin.readline())
tree = []
bet_tree = []
result = 0

#가로수 저장
for i in range(n):
    tree.append(int(sys.stdin.readline().rstrip()))
#가로수 간격 저장
for i in range(n-1):
    bet_tree.append(tree[i+1]-tree[i])

#가로수 간격의 최대공약수 찾기
gcd = bet_tree[0]
for i in range(1,len(bet_tree)):
    gcd = math.gcd(gcd,bet_tree[i])

#가로수 간격 //최대공약수 -1 의 합이 답
for i in range(len(bet_tree)):
    result += bet_tree[i] // gcd -1
print(result)

풀이

가로수 간격 / 가로수 사이의 간격의 최대공약수 -1 의 합이 정답이다.

728x90

문제

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.

  1. 현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
  2. 나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치 한다. 그렇지 않다면 바로 인쇄를 한다.

예를 들어 Queue에 4개의 문서(A B C D)가 있고, 중요도가 2 1 4 3 라면 C를 인쇄하고, 다음으로 D를 인쇄하고 A, B를 인쇄하게 된다.

여러분이 할 일은, 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 것이다. 예를 들어 위의 예에서 C문서는 1번째로, A문서는 3번째로 인쇄되게 된다.

입력

첫 줄에 테스트케이스의 수가 주어진다. 각 테스트케이스는 두 줄로 이루어져 있다.

테스트케이스의 첫 번째 줄에는 문서의 개수 N(1 ≤ N ≤ 100)과, 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N)이 주어진다. 이때 맨 왼쪽은 0번째라고 하자. 두 번째 줄에는 N개 문서의 중요도가 차례대로 주어진다. 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

출력

각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.

코드

import sys
T = int(sys.stdin.readline())
for i in range(T):
    n,m = map(int,sys.stdin.readline().split())
    q = list(map(int,sys.stdin.readline().split()))
    check = [0 for _ in range(n)]
    check[m] = 1
    cnt = 0

    while True:
        if q[0] == max(q):
            cnt+=1
            if check[0] != 1:
                del q[0]
                del check[0]
            else:
                print(cnt)
                break
        else:
            q.append(q[0])
            check.append(check[0])
            del q[0]
            del check[0]

풀이

필요한 것 

1) 우선순위 저장

2) 인덱스 저장

3) 찾아야 하는 인덱스 저장

4) 정답 cnt

 

리스트를 내림차순으로 정렬하는 과정에서 맨 처음 원소가 max값이면 cnt+=1 을 하고 리스트에서 꺼낸다. 

그 다음 max 값을 cnt+=1 하고 또 꺼낸다.

이 때, 원소 값을 꺼낼 때 인덱스를 체크하는 값도 같이 꺼낸다.

인덱스를 체크할 때, 찾고자 하는 인덱스면 끝낸다.

+ Recent posts