문제 https://www.acmicpc.net/problem/1850 1850번: 최대공약수 모든 자리가 1로만 이루어져있는 두 자연수 A와 B가 주어진다. 이때, A와 B의 최대 공약수를 구하는 프로그램을 작성하시오. 예를 들어, A가 111이고, B가 1111인 경우에 A와 B의 최대공약수는 1이고, A www.acmicpc.net 모든 자리가 1로만 이루어져있는 두 자연수 A와 B가 주어진다. 이때, A와 B의 최대 공약수를 구하는 프로그램을 작성하시오. 예를 들어, A가 111이고, B가 1111인 경우에 A와 B의 최대공약수는 1이고, A가 111이고, B가 111111인 경우에는 최대공약수가 111이다. 입력 첫째 줄에 두 자연수 A와 B를 이루는 1의 개수가 주어진다. 입력되는 수는 263..
문제 https://www.acmicpc.net/problem/1783 1783번: 병든 나이트 첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다. www.acmicpc.net 병든 나이트가 N × M 크기 체스판의 가장 왼쪽아래 칸에 위치해 있다. 병든 나이트는 건강한 보통 체스의 나이트와 다르게 4가지로만 움직일 수 있다. 2칸 위로, 1칸 오른쪽 1칸 위로, 2칸 오른쪽 1칸 아래로, 2칸 오른쪽 2칸 아래로, 1칸 오른쪽 병든 나이트는 여행을 시작하려고 하고, 여행을 하면서 방문한 칸의 수를 최대로 하려고 한다. 병든 나이트의 이동 횟수가 4번보다 적지 않다면, 이동 방법을 모두 한 번씩 사용해야 한다. 이동 횟수가 4번보..
문제 https://www.acmicpc.net/problem/1747 1747번: 소수&팰린드롬 어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고, www.acmicpc.net 어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고, 소수이면서 팰린드롬인 수 중에서, 가장 작은 수를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 N이 주어진다. 출력 첫째 줄에..
문제 https://www.acmicpc.net/problem/1744 1744번: 수 묶기 길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에 www.acmicpc.net 길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에 상관없이 묶을 수 있다. 하지만, 같은 위치에 있는 수(자기 자신)를 묶는 것은 불가능하다. 그리고 어떤 수를 묶게 되면, 수열의 합을 구할 때 묶은 수는 서로 곱한 후에 더한다. 예를 들면, ..
문제 https://www.acmicpc.net/problem/1725 1725번: 히스토그램 첫 행에는 N (1 ≤ N ≤ 100,000) 이 주어진다. N은 히스토그램의 가로 칸의 수이다. 다음 N 행에 걸쳐 각 칸의 높이가 왼쪽에서부터 차례대로 주어진다. 각 칸의 높이는 1,000,000,000보다 작거나 같은 www.acmicpc.net 히스토그램에 대해서 알고 있는가? 히스토그램은 아래와 같은 막대그래프를 말한다. 각 칸의 간격은 일정하고, 높이는 어떤 정수로 주어진다. 위 그림의 경우 높이가 각각 2 1 4 5 1 3 3이다. 이러한 히스토그램의 내부에 가장 넓이가 큰 직사각형을 그리려고 한다. 아래 그림의 빗금 친 부분이 그 예이다. 이 직사각형의 밑변은 항상 히스토그램의 아랫변에 평행하게 ..
문제 https://www.acmicpc.net/problem/1707 1707번: 이분 그래프 입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에 www.acmicpc.net 그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다. 그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오. 입력 입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다...
문제 https://www.acmicpc.net/problem/1699 1699번: 제곱수의 합 어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다 www.acmicpc.net 어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다. 이 경우, 수학자 숌크라테스는 “11은 3개 항의 제곱수 합으로 표현할 수 있다.”라고 말한다. 또한 11은 그보다 적은..
문제 https://www.acmicpc.net/problem/1697 1697번: 숨바꼭질 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 www.acmicpc.net 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다. 수빈이와 동생의..
병든 나이트가 N × M 크기 체스판의 가장 왼쪽아래 칸에 위치해 있다. 병든 나이트는 건강한 보통 체스의 나이트와 다르게 4가지로만 움직일 수 있다.
2칸 위로, 1칸 오른쪽
1칸 위로, 2칸 오른쪽
1칸 아래로, 2칸 오른쪽
2칸 아래로, 1칸 오른쪽
병든 나이트는 여행을 시작하려고 하고, 여행을 하면서 방문한 칸의 수를 최대로 하려고 한다. 병든 나이트의 이동 횟수가 4번보다 적지 않다면, 이동 방법을 모두 한 번씩 사용해야 한다. 이동 횟수가 4번보다 적은 경우(방문한 칸이 5개 미만)에는 이동 방법에 대한 제약이 없다.
체스판의 크기가 주어졌을 때, 병든 나이트가 여행에서 방문할 수 있는 칸의 최대 개수를 구해보자.
입력
첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다.
출력
병든 나이트가 여행에서 방문할 수 있는 칸의 개수중 최댓값을 출력한다.
코드
import sys
input=sys.stdin.readline
n, m=map(int, input().split())
if n == 1:
print(1)
elif n == 2:
print(min(4, (m-1)//2+1))
elif m <= 6:
print(min(4, m))
else:
print(m-2)
문제 해결
처음엔 DFS와 BFS를 이용하는 문제인 줄 알았으나, 나이트의 움직임이 4가지로 정해져 있어서 위아래와 오른쪽 방향으로만 정해져있어서 조건 분기, 그리디로 풀 수 있는 문제였다.
어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다.
어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고, 소수이면서 팰린드롬인 수 중에서, 가장 작은 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다.
출력
첫째 줄에 조건을 만족하는 수를 출력한다.
코드
import sys, math
input=sys.stdin.readline
visited=[False,False]+ [True]*(1005000)
for i in range(2,int(math.sqrt(1005001))+1):
if visited[i]==True:
for j in range(2*i,1005001, i):
visited[j]=False
def check(n):
tmp=str(n)
tmp1=tmp[::-1]
if tmp==tmp1: return 1
else: return 0
n=int(input())
for i in range(n,1005001):
if check(i)==1 and visited[i]==True:
print(i)
break
문제 해결
에라토스테네스의 체와 문자열 일치를 섞은 문제이다. 다만 이문제에서 주의 해야할 점은 1 ≤ N ≤ 1,000,000이다.
문제 조건은 N보다 크거나 같고, 소수이면서 팰린드롬인 수를 찾는 것이기 때문에 에라토스테네스의 체를 구할때 1000000보다 큰 수까지 체크해 줘야한다.(1003001가 다음 소수이면서 팰린드롬인수)
길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에 상관없이 묶을 수 있다. 하지만, 같은 위치에 있는 수(자기 자신)를 묶는 것은 불가능하다. 그리고 어떤 수를 묶게 되면, 수열의 합을 구할 때 묶은 수는 서로 곱한 후에 더한다.
예를 들면, 어떤 수열이 {0, 1, 2, 4, 3, 5}일 때, 그냥 이 수열의 합을 구하면 0+1+2+4+3+5 = 15이다. 하지만, 2와 3을 묶고, 4와 5를 묶게 되면, 0+1+(2*3)+(4*5) = 27이 되어 최대가 된다.
수열의 모든 수는 단 한번만 묶거나, 아니면 묶지 않아야한다.
수열이 주어졌을 때, 수열의 각 수를 적절히 묶었을 때, 그 합이 최대가 되게 하는 프로그램을 작성하시오.
입력
첫째 줄에 수열의 크기 N이 주어진다. N은 50보다 작은 자연수이다. 둘째 줄부터 N개의 줄에 수열의 각 수가 주어진다. 수열의 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.
출력
수를 합이 최대가 나오게 묶었을 때 합을 출력한다. 정답은 항상 231보다 작다.
코드
import sys
n=int(input())
pos=[] # 양수를 저장할 리스트
neg=[] # 0과 음수를 저장할 리스트 (0을 음수취급)
total=0
for i in range(n):
num=int(sys.stdin.readline())
if num>1:
pos.append(num)
elif num==1: # 1은 양수와 음수모두 만나도 더하기만 진행
total+=1
else:
neg.append(num)
pos.sort(reverse=True)
neg.sort()
if len(pos)%2==0:
for i in range(0, len(pos), 2):
total+=pos[i]*pos[i+1]
else:
for i in range(0, len(pos)-1, 2):
total+=pos[i]*pos[i+1]
total+=pos[len(pos)-1]
if len(neg)%2==0:
for i in range(0, len(neg), 2):
total+=neg[i]*neg[i+1]
else:
for i in range(0, len(neg)-1, 2):
total+=neg[i]*neg[i+1]
total+=neg[len(neg)-1]
print(total)
문제 해결
이 문제의 핵심은 양수와 양수가 아닌 수를 저장하는 리스트 두개를 만들어서 저장하는 것이다.
그리고 양수 중에서 1은 특수한 특징을 가지고 있고, 양수임에도 1은 곱셈을 해도 그 자체로 출력되므로 1은 양수를 만났을 때 더해야한다. 그리고 1과 음수가 접해있을때 곱셈을 해도 그 자체로 출력되므로 음수를 만났을 때도 더해야만 한다.이를 활용하여 주어진 조건대로 풀이를 하면 코드를 작성할 수 있다.
각 칸의 간격은 일정하고, 높이는 어떤 정수로 주어진다. 위 그림의 경우 높이가 각각 2 1 4 5 1 3 3이다.
이러한 히스토그램의 내부에 가장 넓이가 큰 직사각형을 그리려고 한다. 아래 그림의 빗금 친 부분이 그 예이다. 이 직사각형의 밑변은 항상 히스토그램의 아랫변에 평행하게 그려져야 한다.
주어진 히스토그램에 대해, 가장 큰 직사각형의 넓이를 구하는 프로그램을 작성하시오.
입력
첫 행에는 N (1 ≤ N ≤ 100,000) 이 주어진다. N은 히스토그램의 가로 칸의 수이다. 다음 N 행에 걸쳐 각 칸의 높이가 왼쪽에서부터 차례대로 주어진다. 각 칸의 높이는 1,000,000,000보다 작거나 같은 자연수 또는 0이다.
출력
첫째 줄에 가장 큰 직사각형의 넓이를 출력한다. 이 값은 20억을 넘지 않는다.
코드
n = int(input())
result = 0
s = []
data = []
for i in range(n):
data.append(int(input()))
#왼쪽부터 검사
for i in range(n):
while s and data[s[-1]] > data[i]:
height = data[s[-1]]
s.pop()
width = i
#4 5 1 같은 경우 5 pop 후 4 -> 너비 2만들기 위해
if s:
width = (i - s[-1] - 1)
result = max(result, width * height)
s.append(i)
#스택에서 오른쪽 높이부터 검사
while s:
height = data[s[-1]]
s.pop()
width = n
if s:
width = (n - s[-1] - 1)
result = max(result, width * height)
print(result)
그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호 u, v (u ≠ v)가 빈 칸을 사이에 두고 주어진다.
출력
K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.
제한
2 ≤ K ≤ 5
1 ≤ V ≤ 20,000
1 ≤ E ≤ 200,000
코드
import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline
def dfs(start,group):
visited[start]=group
for i in graph[start]:
if visited[i]==0:
if not dfs(i,-group):
return False
elif visited[i]==visited[start]:
return False
return True
K = int(input())
for _ in range(K):
V, E = map(int, input().split())
graph = [[] for _ in range(V+1)]
visited = [0] * (V+1)
result = True
for _ in range(E):
u, v = map(int, input().split())
graph[u].append(v)
graph[v].append(u)
for i in range(1, V+1):
if visited[i] == 0: # 방문하지 않은 정점이면 dfs 수행
result= dfs(i,1) # 이분 그래프가 아니라면 탐색 중단
if result == False:
break
print('YES' if result else 'NO')
from collections import deque
import sys
input = sys.stdin.readline
def bfs(start):
queue = deque([start])
visited[start] = 1
while queue:
v = queue.popleft()
for i in graph[v]:
if visited[i] == 0:
queue.append(i)
visited[i] = -visited[v]
elif visited[i] == visited[v]: # 이미 방문한 정점이 같은 그룹이라면 False
return False
return True
K = int(input())
for _ in range(K):
V, E = map(int, input().split())
graph = [[] for _ in range(V+1)]
visited = [0] * (V+1)
result = True
for _ in range(E):
u, v = map(int, input().split())
graph[u].append(v)
graph[v].append(u)
for i in range(1, V+1):
if visited[i] == 0: # 방문하지 않은 정점이면 bfs 수행
if not bfs(i): # 이분 그래프가 아니라면 탐색 중단
result = False
break
print('YES' if result else 'NO')
문제 해결
주어진 이분그래프 문제를 BFS와 DFS방식으로 모두 풀어봤습니다.
추가적으로 이분그래프의 개념을 참고하면 좋을 것 같습니다.
이분 그래프(Bipartite Graph)란?
인접한 정점끼리 서로 다른 색으로 칠해서 모든 정점을 두 가지 색으로만 칠할 수 있는 그래프입니다.
탐색을 진행하며, 현재 노드와 이웃한 노드의 색을 확인하고, 동일한 색으로 칠해져있다면, 이분 그래프가 아닌 것으로 판단합니다.
어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다. 이 경우, 수학자 숌크라테스는 “11은 3개 항의 제곱수 합으로 표현할 수 있다.”라고 말한다. 또한 11은 그보다 적은 항의 제곱수 합으로 표현할 수 없으므로, 11을 그 합으로써 표현할 수 있는 제곱수 항의 최소 개수는 3이다.
주어진 자연수 N을 이렇게 제곱수들의 합으로 표현할 때에 그 항의 최소개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 100,000)
출력
주어진 자연수를 제곱수의 합으로 나타낼 때에 그 제곱수 항의 최소 개수를 출력한다.
코드
import sys
input=sys.stdin.readline
n=int(input())
dp=[i for i in range(n+1)]
for i in range(1,n+1):
for j in range(1,i):
if j*j>i:
break
if dp[i]>dp[i-j*j]+1:
dp[i]=dp[i-j*j]+1
print(dp[n])
문제 해결
DP를 활용하여 풀이하는 문제였다.
dp[N] = min(dp[N], dp[N - 제곱수] + 1)
이를 이용해서 풀거나 주어진 조건을 일일히 계산하여 min함수를 사용하지 않고 주어진 코드처럼 풀이해도 된다.
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
코드
import sys
input=sys.stdin.readline
from collections import deque
Max = 10 ** 5
n,k = map(int,input().split())
visitedCnt = [0]*(Max+1)
def bfs():
queue = deque()
queue.append([n,0])
while queue:
idx,cnt = queue.popleft()
if(idx == k):
print(cnt)
break
pos = [idx-1,idx+1,idx*2]
for i in pos:
if 0 <= i <= Max and not visitedCnt[i]:
visitedCnt[i] = visitedCnt[idx] + 1
queue.append([i,visitedCnt[i]])
bfs()
문제 해결
정점 x가 정점 x-1, x+1, x*2와 연결되어 있는 형태임을 알고 BFS를 적용하였다.
또, 처음에는 방문처리가 필요하지 않다고 생각하였으나 방문처리를 해주지 않으면 중복 탐색에 발생하여 메모리 초과가 발생하여서 방문처리까지 완성하여 코드를 작성했다.