def get_divide_list(num):
result = []
for i in range(1,int(num**0.5)+1):
if not num%i:
result.extend([i,num//i])
result = list(set(result))
result.remove(1)
return result
N = int(input())
arr = list(map(int,input().split()))
X = int(input())
X_list = get_divide_list(X)
answer = 0
cnt = 0
for num in arr:
for x_num in X_list:
if not num%x_num:
break
else:
answer += num
cnt += 1
print(answer/cnt)
이 문제 또한, 소수를 구하면 된다. 약수를 구할때, 구하고자하는 수의 sqrt만
탐색을 해주면 좀 더 빠르게 할 수 있다는 점을 생각하고 풀면 편한다.
만약 1을 제외한 약수들을 구한뒤, 약수로 나뉘면, 멈추는 방식으로 해서, 평균을 구했다.
import sys
input = sys.stdin.readline
def get_prim_number(input_Num):
last_num = input_Num
visited = [False for _ in range(last_num+1)]
visited[0] = True
visited[1] = True
result = []
for num in range(2,last_num+1):
if not visited[num]:
result.append(num)
for new_num in range(2*num,last_num+1,num):
visited[new_num] = True
return result
N = int(input())
arr = list(map(int,input().split()))
result = []
max_num = max(arr)
prim_set = get_prim_number(max_num)
for val in arr:
if val in prim_set:
result.append(val)
if len(result)>0:
answer = 1
result = set(result)
for prim in result:
answer*=prim
print(answer)
else:
print(-1)
import sys
input = sys.stdin.readline
N,M = map(int,input().split())
arr = list(map(int,input().split()))
cnt = [0]*(N+1)
for _ in range(M):
command,x,y = map(int,input().split())
x -= 1
if command == 1:
arr[x] = y
elif command == 2:
y -= 1
for ind in range(x,y+1):
arr[ind] = (arr[ind]+1)%2
elif command == 3:
y-=1
for ind in range(x,y+1):
arr[ind] = 0
else:
y -= 1
for ind in range(x,y+1):
arr[ind] = 1
print(*arr)
이 문제는 문제에 주어진 조건대로 배열의 상태를 바꿔주면 되는 문제였다.
전체 배열의 크기가 4000이고, 최대 명령이 4000이라,
최악의 경우라 해도 1600만번밖에 안되므로, 문제에 주어진 조건대로 돌리면 되는 문제이다.
import sys
from collections import deque
input = sys.stdin.readline
def calc(i,input_list,flag):
if i == 1:
input_list.rotate(2)
elif i == 2:
input_list.reverse()
input_list.rotate(2)
elif i == 3:
a,b = input_list.popleft(),input_list.popleft()
input_list.insert(1,a)
input_list.insert(3,b)
elif i == 4:
a = input_list.popleft()
input_list.rotate(1)
b = input_list.pop()
input_list.rotate(1)
input_list.append(a)
input_list.append(b)
elif flag and i ==6:
a = input_list.popleft()
input_list.rotate(1)
b = input_list.pop()
input_list.rotate(1)
input_list.append(a)
input_list.append(b)
elif flag and i == 5:
a,b = input_list.popleft(),input_list.popleft()
input_list.insert(1,a)
input_list.insert(3,b)
N,M,R = map(int,input().split())
half_N = N//2
half_M = M//2
arr = [list(map(int,input().split())) for _ in range(N)]
arr_divide = {}
for i in range(4):
temp = []
quo = i//2
mod = i%2
start_x = quo*(N//2)
end_x = (quo+1)*(N//2)
start_y = mod*(M//2)
end_y = (mod+1)*(M//2)
for x in range(start_x,end_x):
tmp = []
for y in range(start_y,end_y):
tmp.append(arr[x][y])
temp.append(tmp)
arr_divide[i+1] = temp
command_cnt = [0 for _ in range(7)]
command_list = list(map(int,input().split()))
small_list = deque([1,2,3,4])
mini_rotate = deque([0,1,2,3])
for i in command_list:
calc(i,small_list,True)
calc(i,mini_rotate,False)
position = [[0,0],[0,M//2-1],[N//2-1,0],[N//2-1,M//2-1]]
one,two,three = mini_rotate.popleft(),mini_rotate.popleft(),mini_rotate.popleft()
for i in range(4):
origin = position[one]
left_origin = position[two]
bottom_origin = position[three]
if origin[0] == left_origin[0] and origin[1] == bottom_origin[1] :
if origin[1] > left_origin[1]:
dy = -1
else:
dy = 1
if origin[0] > bottom_origin[0]:
dx = -1
else:
dx = 1
temp = []
for x in range(abs(bottom_origin[0]-origin[0])+1):
tmp = []
for y in range(abs(origin[1] - left_origin[1])+1):
tmp.append(arr_divide[i+1][origin[0]+x*dx][origin[1]+y*dy])
temp.append(tmp)
arr_divide[i+1] = temp
else:
if origin[0] > left_origin[0]:
dy = -1
else:
dy = 1
if origin[1] > bottom_origin[1]:
dx = -1
else:
dx = 1
temp = []
for x in range(abs(bottom_origin[1]-origin[1])+1):
tmp = []
for y in range(abs(left_origin[0]-origin[0])+1):
tmp.append(arr_divide[i+1][origin[0]+dy*y][origin[1]+dx*x])
temp.append(tmp)
arr_divide[i+1] = temp
last_N= len(arr_divide[1])*2
last_M = len(arr_divide[1][0])*2
result = [[0 for _ in range(last_M)] for _ in range(last_N)]
for i in range(4):
idx = small_list.popleft()
quo = i//2
mod = i%2
start_x = quo*(last_N//2)
start_y = mod*(last_M//2)
my_array = arr_divide[idx]
for x in range(last_N//2):
for y in range(last_M//2):
result[start_x+x][start_y+y] = my_array[x][y]
for x in range(last_N):
for y in range(last_M):
print(result[x][y],end=' ')
print()
배열 돌리기 시리즈의 5번째이다.
이 배열돌리기는 전체를 돌리면 무조건 시간초과가 날수밖에 없다.
왜냐하면 최대 100*100의 행렬이 오는데 그걸 200만번 수행을 하면 터질수 밖에 없다.
그렇다 면 이 문제를 해결하는 방법은 다음과 같다.
이 문제에서 행렬을 크게 4부위로 나눌수 있다.
처음 배열을 다음과 같이 4등분을 해주자(문제에서는 1 2/ 3 4 가 아니라, 1 2 / 4 3 형태이지만, 그냥 편하대로 하면 된다.)
그러면 1번 돌리기는 다음과 같이 표현할 수 있다.
위 아래의 배열이 바뀌고, 그리고 그안의 있는 값도 상하반전이 된 것을 알 수 있다.
2번 돌리기는
좌우 반전이 되고, 그리기 도구에서 안의 숫자를 좌우반전을 하는게 없어서 표현 못했지만, 그 안에 있는 작은 배열들도 좌우 반전이 되어야한다.
3번 돌리기는
오른쪽으로 90도 돌면서 그 안의 있는 값들도 90도로 돌리면 된다.
4번 돌리기는 왼쪽으로 90도로 돌리고, 그 안의 배열들도 같이 왼쪽으로 90도를 돌리면 된다.
5번 돌리기는 3번돌리기와 똑같이 전체 배열의 이동은 같지만, 안의 배열이 돌아가지 않는 모습이다.
그리고 6번 돌리기는 4번돌리기와 전체배열의 이동은 같지만 안의 배열이 돌아가지 않는 모습이다.
이렇게 4등분을 해보면 우리는 알 수 있는 사실이 있다.
전체 배열을 전부 돌릴필요가 없다는 것이다.
1~6번 돌리기를 간략하게 표현할 수 있는 2*2 배열을 돌리기만 하면 된 다는 것을 알 수 있다.
그러면 그 안에 있는 배열들이 돌아가는 것은 어떻게 표현하느냐이다.
위와 같이 한 배열이 있다고 하면, 우리는 네 꼭지점의 위치를 알면 전체 배열이 어떻게 모양이 변한지 알 수 있다.
이러한 특성을 이용해서
mini_rotate에는 각 꼭지점의 위치를 표현한 (0,1,2,3)을 상황에 맞게 돌려주면서, 작은 배열에서 1~4번 돌리기에 해당될때 어떻게 회전되는지를 표현해주었다.
그리고 small_list는 전체 배열을 4등분을 해서, 각 등분된 배열을 1,2,3,4로 매칭시키고, 1~6번 돌리기에 맞게 회전을 시켜 주었다.
mini_rotate를 돌릴때 주의 해야할 것은 나는 행을 x 열을 y로 표현하는 편이다. 돌리다 보면
행과 열이 뒤바뀌어서 행이 dy 열로 이동하는 것이 dx로 뒤바뀔때가 있을 것이다.
그러면 이걸 어떻게 구분할 것이냐,
위의 변수명을 잘못 선언했지만 다음과 같다.
원본 배열에서 (0,0) 이 부분을 origin이라 하겠다.
그리고 (0,M//2) 이부분을 right_origin(코드에서는 left_origin) 이라 부르겠다.
그리고 (N//2,0) 이 부분을 bottom_origin이라 부르겠다.
그러면 우리가 전부 회전을 하고 난뒤에 바뀐 위치에 있는 origin, right_origin, bottom_origin이 있을것이다.
import sys
input = sys.stdin.readline
sys.setrecursionlimit(500000)
def root_dfs(node):
if visited[node]:
return
visited[node] = True
child_list = []
for next_node in tree[node]:
if not visited[next_node]:
child_list.append(next_node)
if len(child_list)==2:
return [node,0]
elif len(child_list) == 1:
return_value = root_dfs(child_list[0])
return_value[1] += tree[node][child_list[0]]
return return_value
else:
return [node,0]
def leef_dfs(node):
if visited[node]:
return
visited[node] = True
child_list = []
for next_node in tree[node]:
if not visited[next_node]:
child_list.append(next_node)
if len(child_list)==0:
return 0
else:
result = 0
for child_node in child_list:
result = max(result,leef_dfs(child_node)+tree[node][child_node])
return result
N,R = map(int,input().split())
tree = [{} for _ in range(N+1)]
for _ in range(N-1):
x,y,b = map(int,input().split())
tree[x][y] = b
tree[y][x] = b
visited = [False for _ in range(N+1)]
root_node_info = root_dfs(R)
visited[root_node_info[0]] = False
leef_dis = leef_dfs(root_node_info[0])
print(root_node_info[1],leef_dis)
2개의 DFS로 나눠서 최초엔 풀었다.
첫번째 풀이는 두개로 나뉘어서 DFS를 했다.
첫 DFS는 기가노드를 찾는것이다. 기가노드를 찾으면 그때의 길이를 저장해놓는다.
그리고 기가노드에서 부터 리프노드까지 최대 길이를 찾아내는 방식으로 해서 구했다.
import sys
input = sys.stdin.readline
sys.setrecursionlimit(300000)
def root_dfs(node,dis):
if visited[node]:
return
visited[node] = True
count = 0
nexts = -1
distance = 0
for next_node in tree[node]:
if not visited[next_node]:
count += 1
nexts = next_node
distance += tree[node][next_node]
if count == 1:
return root_dfs(nexts,dis+distance)
else:
return [node,dis]
def leaf_dfs(node,dis):
global leef_dis
visited[node] = True
count = 0
for next_node in tree[node]:
if not visited[next_node]:
leaf_dfs(next_node,dis+tree[node][next_node])
count += 1
if not count:
leef_dis = max(leef_dis,dis)
N,R = map(int,input().split())
tree = [{} for _ in range(N+1)]
for _ in range(N-1):
x,y,b = map(int,input().split())
tree[x][y] = b
tree[y][x] = b
visited = [False for _ in range(N+1)]
root_dis = root_dfs(R,0)
leef_dis = 0
leaf_dfs(root_dis[0],0)
print(root_dis[1],leef_dis)
두번째 풀이는 좀더 깔끔한 풀이이다.
count를 별도로 세주어서 기가노드인지 리프노드인지 구분을 해주었다.
기가노드가 아닐때에는 재귀를 해주면서 distance를 더해주고, 만약 기가노드일때는 재귀를 머추고, 기가노드의 위치와
지금까지 누적된 거리를 반환해준다.
leaf_dfs도 비슷한 과정을 겪는다.
leaf_dfs를 계속 재귀를 통해 가면서 leaf_node에 도착하면 현재까지 누적된 값과 최대값과 비교를 해서 더 큰 값을 넣어주면 된다.