ㅌ문제:

한국도로공사는 고속도로의 유비쿼터스화를 위해 고속도로 위에 N개의 센서를 설치하였다. 문제는 이 센서들이 수집한 자료들을 모으고 분석할 몇 개의 집중국을 세우는 일인데, 예산상의 문제로, 고속도로 위에 최대 K개의 집중국을 세울 수 있다고 한다.

각 집중국은 센서의 수신 가능 영역을 조절할 수 있다. 집중국의 수신 가능 영역은 고속도로 상에서 연결된 구간으로 나타나게 된다. N개의 센서가 적어도 하나의 집중국과는 통신이 가능해야 하며, 집중국의 유지비 문제로 인해 각 집중국의 수신 가능 영역의 길이의 합을 최소화해야 한다.

편의를 위해 고속도로는 평면상의 직선이라고 가정하고, 센서들은 이 직선 위의 한 기점인 원점으로부터의 정수 거리의 위치에 놓여 있다고 하자. 따라서, 각 센서의 좌표는 정수 하나로 표현된다. 이 상황에서 각 집중국의 수신 가능영역의 거리의 합의 최솟값을 구하는 프로그램을 작성하시오. 단, 집중국의 수신 가능영역의 길이는 0 이상이며 모든 센서의 좌표가 다를 필요는 없다.

입력:

첫째 줄에 센서의 개수 N(1 ≤ N ≤ 10,000), 둘째 줄에 집중국의 개수 K(1 ≤ K ≤ 1000)가 주어진다. 셋째 줄에는 N개의 센서의 좌표가 한 개의 정수로 N개 주어진다. 각 좌표 사이에는 빈 칸이 하나 있으며, 좌표의 절댓값은 1,000,000 이하이다.

출력:

첫째 줄에 문제에서 설명한 최대 K개의 집중국의 수신 가능 영역의 길이의 합의 최솟값을 출력한다.

풀이방법:

 해당 문제는 N개의 센서가 있을 때, K개의 그룹으로 만드는 것이 목적이다. 따라서 다음과 같은 알고리즘 순서대로 진행한다.

 

1. 센서들을 오름차순으로 정렬한다.

2. 각 센서들간의 차이를 구한다.

3. 각 센서들간의 차이를 내림차순으로 정렬한다.

4. 앞에서 부터 K-1개를 제외한 나머지들을 다 합한다.

1
2
3
4
5
6
7
8
9
10
11
12
= int(input())
= int(input())
numbers = sorted(list(map(int,input().split())))
 
diff = []
for i,v in enumerate(numbers):
    if i==0:
        continue
    diff.append(v - numbers[i-1])
    
diff = sorted(diff, reverse=True)
print(sum(diff[K-1:]))
cs

문제링크:

https://www.acmicpc.net/problem/2212

 

2212번: 센서

첫째 줄에 센서의 개수 N(1 ≤ N ≤ 10,000), 둘째 줄에 집중국의 개수 K(1 ≤ K ≤ 1000)가 주어진다. 셋째 줄에는 N개의 센서의 좌표가 한 개의 정수로 N개 주어진다. 각 좌표 사이에는 빈 칸이 하나 있

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1063. 킹  (0) 2022.03.15
[BOJ]2195. 문자열 복사  (0) 2022.03.10
[BOJ]17609. 회문  (0) 2022.03.03
[BOJ]1766. 문제집  (0) 2022.03.01
[BOJ]1256. 사전  (0) 2022.02.24

문제:

회문(回文) 또는 팰린드롬(palindrome)은 앞 뒤 방향으로 볼 때 같은 순서의 문자로 구성된 문자열을 말한다. 예를 들어 ‘abba’ ‘kayak’, ‘reviver’, ‘madam’은 모두 회문이다. 만일 그 자체는 회문이 아니지만 한 문자를 삭제하여 회문으로 만들 수 있는 문자열이라면 우리는 이런 문자열을 “유사회문”(pseudo palindrome)이라고 부른다. 예를 들어 ‘summuus’는 5번째나 혹은 6번째 문자 ‘u’를 제거하여 ‘summus’인 회문이 되므로 유사회문이다.

여러분은 제시된 문자열을 분석하여 그것이 그 자체로 회문인지, 또는 한 문자를 삭제하면 회문이 되는 “유사회문”인지, 아니면 회문이나 유사회문도 아닌 일반 문자열인지를 판단해야 한다. 만일 문자열 그 자체로 회문이면 0, 유사회문이면 1, 그 외는 2를 출력해야 한다. 

입력:

입력의 첫 줄에는 주어지는 문자열의 개수를 나타내는 정수 T(1 ≤ T ≤ 30)가 주어진다. 다음 줄부터 T개의 줄에 걸쳐 한 줄에 하나의 문자열이 입력으로 주어진다. 주어지는 문자열의 길이는 3 이상 100,000 이하이고, 영문 알파벳 소문자로만 이루어져 있다.

출력:

각 문자열이 회문인지, 유사 회문인지, 둘 모두 해당되지 않는지를 판단하여 회문이면 0, 유사 회문이면 1, 둘 모두 아니면 2를 순서대로 한 줄에 하나씩 출력한다.

풀이방법:

 일반적인 회문 문제와는 다르게 한 번의 기회를 더 제공하는 '유사회문'이라는 추가 조건이 더 있다. 따라서 일반적인 회문을 판정하는 함수에 추가적으로 하나의 문자를 삭제하고 추가로 회문인지 판단하는 함수를 더 추가하도록 한다. 이 때, 하나의 문자를 제거할 때, 왼쪽의 문자, 오른쪽의 문자를 한번씩 모두 제거하여 유사회문이 되는지 판단하여야 한다. 만약 한쪽을 우선적으로 판단하면 오류가 되는 케이스를 발견할 수 있다.

 따라서 일반적인 회문이라면 0을 반환하고, 하나를 제거해야 하는 상황인데 왼쪽, 오른쪽을 둘 다 확인했을 때, 하나가 가능하다면 1, 둘 다 불가능하다면 2를 반환하여 출력을 할 수 있도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def next_palindrome(s, left, right):
    while left < right:
        if s[left]==s[right]:
            left+=1
            right-=1
        else:
            return 0
    return 1
 
def is_palindrome(s, left, right):
    while left < right:
        if s[left]==s[right]:
            left+=1
            right-=1
        else:
            left_count = next_palindrome(s, left+1, right)
            right_count = next_palindrome(s, left, right-1)
            if left_count or right_count:
                return 1
            else:
                return 2
    return 0
 
= int(input())
for _ in range(T):
    string = input()
    answer = is_palindrome(string, 0len(string)-1)
    if answer >= 2:
        answer = 2
    print(answer)
cs

문제링크:

https://www.acmicpc.net/problem/17609

 

17609번: 회문

각 문자열이 회문인지, 유사 회문인지, 둘 모두 해당되지 않는지를 판단하여 회문이면 0, 유사 회문이면 1, 둘 모두 아니면 2를 순서대로 한 줄에 하나씩 출력한다.

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2195. 문자열 복사  (0) 2022.03.10
[BOJ]2212. 센서  (0) 2022.03.08
[BOJ]1766. 문제집  (0) 2022.03.01
[BOJ]1256. 사전  (0) 2022.02.24
[BOJ]10164. 격자상의 경로  (0) 2022.02.22

문제:

민오는 1번부터 N번까지 총 N개의 문제로 되어 있는 문제집을 풀려고 한다. 문제는 난이도 순서로 출제되어 있다. 즉 1번 문제가 가장 쉬운 문제이고 N번 문제가 가장 어려운 문제가 된다.

어떤 문제부터 풀까 고민하면서 문제를 훑어보던 민오는, 몇몇 문제들 사이에는 '먼저 푸는 것이 좋은 문제'가 있다는 것을 알게 되었다. 예를 들어 1번 문제를 풀고 나면 4번 문제가 쉽게 풀린다거나 하는 식이다. 민오는 다음의 세 가지 조건에 따라 문제를 풀 순서를 정하기로 하였다.

  1. N개의 문제는 모두 풀어야 한다.
  2. 먼저 푸는 것이 좋은 문제가 있는 문제는, 먼저 푸는 것이 좋은 문제를 반드시 먼저 풀어야 한다.
  3. 가능하면 쉬운 문제부터 풀어야 한다.

예를 들어서 네 개의 문제가 있다고 하자. 4번 문제는 2번 문제보다 먼저 푸는 것이 좋고, 3번 문제는 1번 문제보다 먼저 푸는 것이 좋다고 하자. 만일 4-3-2-1의 순서로 문제를 풀게 되면 조건 1과 조건 2를 만족한다. 하지만 조건 3을 만족하지 않는다. 4보다 3을 충분히 먼저 풀 수 있기 때문이다. 따라서 조건 3을 만족하는 문제를 풀 순서는 3-1-4-2가 된다.

문제의 개수와 먼저 푸는 것이 좋은 문제에 대한 정보가 주어졌을 때, 주어진 조건을 만족하면서 민오가 풀 문제의 순서를 결정해 주는 프로그램을 작성하시오.

입력:

첫째 줄에 문제의 수 N(1 ≤ N ≤ 32,000)과 먼저 푸는 것이 좋은 문제에 대한 정보의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 둘째 줄부터 M개의 줄에 걸쳐 두 정수의 순서쌍 A,B가 빈칸을 사이에 두고 주어진다. 이는 A번 문제는 B번 문제보다 먼저 푸는 것이 좋다는 의미이다.

항상 문제를 모두 풀 수 있는 경우만 입력으로 주어진다.

출력:

첫째 줄에 문제 번호를 나타내는 1 이상 N 이하의 정수들을 민오가 풀어야 하는 순서대로 빈칸을 사이에 두고 출력한다.

풀이방법:

이 문제는 '사이클'이 없으며 '방향'만 존재하는 그래프에서 정점을 나열하는 방법으로 풀 수 있다. 이러한 문제 푸는 방법을 위상 정렬 (Topological Sort)라고 한다.

 또한 시간을 최소화하기 위해서 최소 힙을 사용한 우선순위 큐를 사용하도록 한다. 문제는 다음과 같은 알고리즘 순서로 해결한다.

 

1. 정점과 연결된 그래프와 해당 정점과 연결된 정점의 개수 리스트를 만든다.

2. 연결된 정점 개수 리스트(In_degree)가 없는 정점부터 먼저 최소 힙에 넣어준다.

3. 해당 정점과 연결되어 있는 정점(In_degree)들부터 하나씩 제거해 준다.

4. 연결된 정점 개수가 없는 정점이 생긴다면 최소 힙을 다시 넣어준다. 이후 3)으로 돌아간다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import sys
import heapq
 
input = sys.stdin.readline
 
N, M = map(int,input().split())
problems = [[] for i in range(N+1)]
in_degree = [0 for i in range(N+1)]
 
= []
 
for _ in range(M):
    a, b = map(int,input().split())
    problems[a].append(b)
    in_degree[b]+=1
    
for i in range(1, N+1):
    if in_degree[i] == 0:
        heapq.heappush(h, i)
        
answer =[]
while h:
    tmp = heapq.heappop(h)
    answer.append(tmp)
    for j in problems[tmp]:
        in_degree[j] -=1
        if in_degree[j] == 0:
            heapq.heappush(h,j)
            
print(*answer)
cs

문제링크:

https://www.acmicpc.net/problem/1766

 

1766번: 문제집

첫째 줄에 문제의 수 N(1 ≤ N ≤ 32,000)과 먼저 푸는 것이 좋은 문제에 대한 정보의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 둘째 줄부터 M개의 줄에 걸쳐 두 정수의 순서쌍 A,B가 빈칸을 사이에 두고 주

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2212. 센서  (0) 2022.03.08
[BOJ]17609. 회문  (0) 2022.03.03
[BOJ]1256. 사전  (0) 2022.02.24
[BOJ]10164. 격자상의 경로  (0) 2022.02.22
[BOJ]1916. 최소비용 구하기  (0) 2022.02.18

문제:

동호와 규완이는 212호에서 문자열에 대해 공부하고 있다. 김진영 조교는 동호와 규완이에게 특별 과제를 주었다. 특별 과제는 특별한 문자열로 이루어 진 사전을 만드는 것이다. 사전에 수록되어 있는 모든 문자열은 N개의 "a"와 M개의 "z"로 이루어져 있다. 그리고 다른 문자는 없다. 사전에는 알파벳 순서대로 수록되어 있다.

규완이는 사전을 완성했지만, 동호는 사전을 완성하지 못했다. 동호는 자신의 과제를 끝내기 위해서 규완이의 사전을 몰래 참조하기로 했다. 동호는 규완이가 자리를 비운 사이에 몰래 사전을 보려고 하기 때문에, 문자열 하나만 찾을 여유밖에 없다.

N과 M이 주어졌을 때, 규완이의 사전에서 K번째 문자열이 무엇인지 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 세 정수 N, M, K가 순서대로 주어진다.

출력:

첫째 줄에 규완이의 사전에서 K번째 문자열을 출력한다. 만약 규완이의 사전에 수록되어 있는 문자열의 개수가 K보다 작으면 -1을 출력한다.

풀이방법:

해당 문제는 다음과 같은 알고리즘으로 해결하도록 한다.

 

1. n개의 a m개의 z가 있다고 했을 때, a를 하나 제거했을 때의 경우의 수를 구한다.

2. 이 갯수가 k보다 크다면 a를 먼저 배치한다.

2-1. 이 갯수가 k보다 작다면 z를 먼저 배치하고, k에서 1에서 구한 값을 빼준다.

3. n이나 m 둘 중 하나가 0이 될 때까지를 이를 반복하고, 남은 n과 m이 있다면 다 이어붙이고 종료한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from math import factorial
def nCr(n,r):
    return factorial(n) / (factorial(r)* factorial(n-r))
 
n, m, k = map(int,input().split())
 
if nCr(n+m,n)<k:
    answer = -1
else:
    answer = ""
    while True:
        if n==0 or m==0:
            answer += "a"*n
            answer += "z"*m
            break
        
        pivot = nCr(n+m-1,m)
        if k <= pivot:
            answer += "a"
            n-=1
        else:
            answer += "z"
            m -= 1
            k -=pivot
            
print(answer)
cs

문제링크:

https://www.acmicpc.net/problem/1256

 

1256번: 사전

동호와 규완이는 212호에서 문자열에 대해 공부하고 있다. 김진영 조교는 동호와 규완이에게 특별 과제를 주었다. 특별 과제는 특별한 문자열로 이루어 진 사전을 만드는 것이다. 사전에 수록되

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]17609. 회문  (0) 2022.03.03
[BOJ]1766. 문제집  (0) 2022.03.01
[BOJ]10164. 격자상의 경로  (0) 2022.02.22
[BOJ]1916. 최소비용 구하기  (0) 2022.02.18
[BOJ]11689. GCD(n,k) = 1  (0) 2022.02.16

문제:

행의 수가 N이고 열의 수가 M인 격자의 각 칸에 1부터 N×M까지의 번호가 첫 행부터 시작하여 차례로 부여되어 있다. 격자의 어떤 칸은 ○ 표시가 되어 있다. (단, 1번 칸과 N × M번 칸은 ○ 표시가 되어 있지 않다. 또한, ○ 표시가 되어 있는 칸은 최대 한 개이다. 즉, ○ 표시가 된 칸이 없을 수도 있다.)

행의 수가 3이고 열의 수가 5인 격자에서 각 칸에 번호가 1부터 차례대로 부여된 예가 아래에 있다. 이 격자에서는 8번 칸에 ○ 표시가 되어 있다.

격자의 1번 칸에서 출발한 어떤 로봇이 아래의 두 조건을 만족하면서 N×M번 칸으로 가고자 한다. 

  • 조건 1: 로봇은 한 번에 오른쪽에 인접한 칸 또는 아래에 인접한 칸으로만 이동할 수 있다. (즉, 대각선 방향으로는 이동할 수 없다.)
  • 조건 2: 격자에 ○로 표시된 칸이 있는 경우엔 로봇은 그 칸을 반드시 지나가야 한다. 

위에서 보인 것과 같은 격자가 주어질 때, 로봇이 이동할 수 있는 서로 다른 경로의 두 가지 예가 아래에 있다.

  • 1 → 2 → 3 → 8 → 9 → 10 → 15
  • 1 → 2 → 3 → 8 → 13 → 14 → 15

격자에 관한 정보가 주어질 때 로봇이 앞에서 설명한 두 조건을 만족하면서 이동할 수 있는 서로 다른 경로가 총 몇 개나 되는지 찾는 프로그램을 작성하라

입력:

입력의 첫째 줄에는 격자의 행의 수와 열의 수를 나타내는 두 정수 N과 M(1 ≤ N, M ≤ 15), 그리고 ○로 표시된 칸의 번호를 나타내는 정수 K(K=0 또는 1 < K < N×M)가 차례로 주어지며, 각 값은 공백으로 구분된다. K의 값이 0인 경우도 있는데, 이는 ○로 표시된 칸이 없음을 의미한다. N과 M이 동시에 1인 경우는 없다.

출력:

주어진 격자의 정보를 이용하여 설명한 조건을 만족하는 서로 다른 경로의 수를 계산하여 출력해야 한다. 

풀이방법:

 수학 시간에 배웠던 경로의 갯수 공식을 사용하도록 한다. 사각형이 있고, 되돌아 갈 수 없다는 조건이 있다면 시작점에서 도착점까지 가는 경우의 수는 (가로변의 갯수 + 세로변의 갯수)C(가로변의 갯수 or 세로변의 갯수)다. 이 문제의 경우 격자에 하나의 중심점이 표현되어 있기 때문에, 이 점을 기준으로 두 번의 경우의 수를 구한 다음에 둘을 곱하면 최종 답을 얻을 수 있다.

 따라서 이 문제는 O 표시가 되어 있는 지점의 좌표를 정확하게 계산하고, combination 연산 공식을 구현하여 문제를 해결하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from math import factorial
def nCr(n,r):
    return factorial(n) / (factorial(r)* factorial(n-r))
 
n, m, o = map(int, input().split())
if o:
    if o%m:
        y = (o//m+1)
    else:
        y = o//m
    x = o - ((y-1)*m)
    print(int(nCr(x+y-2, x-1)*nCr(m+n-(x+y), m-x)))
else:
    print(int(nCr(m+n-2, m-1)))
cs

문제링크:

https://www.acmicpc.net/problem/10164

 

10164번: 격자상의 경로

입력의 첫째 줄에는 격자의 행의 수와 열의 수를 나타내는 두 정수 N과 M(1 ≤ N, M ≤ 15), 그리고 ○로 표시된 칸의 번호를 나타내는 정수 K(K=0 또는 1 < K < N×M)가 차례로 주어지며, 각 값은 공백으

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1766. 문제집  (0) 2022.03.01
[BOJ]1256. 사전  (0) 2022.02.24
[BOJ]1916. 최소비용 구하기  (0) 2022.02.18
[BOJ]11689. GCD(n,k) = 1  (0) 2022.02.16
[BOJ]2526. 싸이클  (0) 2022.02.14

문제:

N개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 M개의 버스가 있다. 우리는 A번째 도시에서 B번째 도시까지 가는데 드는 버스 비용을 최소화 시키려고 한다. A번째 도시에서 B번째 도시까지 가는데 드는 최소비용을 출력하여라. 도시의 번호는 1부터 N까지이다.

입력:

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 그리고 그 다음에는 도착지의 도시 번호가 주어지고 또 그 버스 비용이 주어진다. 버스 비용은 0보다 크거나 같고, 100,000보다 작은 정수이다.

그리고 M+3째 줄에는 우리가 구하고자 하는 구간 출발점의 도시번호와 도착점의 도시번호가 주어진다. 출발점에서 도착점을 갈 수 있는 경우만 입력으로 주어진다.

출력:

첫째 줄에 출발 도시에서 도착 도시까지 가는데 드는 최소 비용을 출력한다.

풀이방법:

 한 정점에서 다른 정점으로 가는 최소 비용을 구하는 알고리즘에는 다익스트라 알고리즘이 있다. 따라서 해당 문제를 다익스트라 알고리즘을 사용해서 풀었다.

 해당 문제에서 조심해야 하는 점은 출발 도시와 도착 도시가 한 쌍으로 주어지지 않는다는 것이다. 즉 A 도시에서 C 도시로 이동하는 버스가 여러번 입력으로 들어올 수 있다. 그러므로 입력을 받을 당시에 도시간에 이동하는 비용은 항상 최소가 되도록 유지시켜 준다.

 다익스트라 알고리즘은 heapq를 사용한 방법을 사용하여 구현을 했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import sys
import heapq
 
input = sys.stdin.readline
 
def dijkstra(start):
    q = []
    heapq.heappush(q,(0, start))
    distance[start] = 0
    
    while q:
        dist, now = heapq.heappop(q)
        
        if distance[now] < dist:
            continue
            
        for i, g in enumerate(graph[now]):
            cdist = dist + g
            if cdist < distance[i]:
                distance[i] = cdist
                heapq.heappush(q,(cdist,i))
 
= int(input())
= int(input())
INF = float('inf')
 
graph = [[INF for _ in range(n+1)] for _ in range(n+1)]
distance = [INF]*(n+1)
 
for _ in range(m):
    a, b, c = map(int,input().split())
    if graph[a][b]==INF:
        graph[a][b] = c
    else:
        graph[a][b] = min(graph[a][b],c)
 
start, end = map(int,input().split())
dijkstra(start)
print(distance[end])
cs

문제링크:

https://www.acmicpc.net/problem/1916

 

1916번: 최소비용 구하기

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1256. 사전  (0) 2022.02.24
[BOJ]10164. 격자상의 경로  (0) 2022.02.22
[BOJ]11689. GCD(n,k) = 1  (0) 2022.02.16
[BOJ]2526. 싸이클  (0) 2022.02.14
[BOJ]2641. 다각형그리기  (0) 2022.02.11

문제:

자연수 n이 주어졌을 때, GCD(n, k) = 1을 만족하는 자연수 1 ≤ k ≤ n 의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 자연수 n (1 ≤ n ≤ 1012)이 주어진다.

출력:

GCD(n, k) = 1을 만족하는 자연수 1 ≤ k ≤ n 의 개수를 출력한다.

풀이방법:

https://ko.wikipedia.org/wiki/%EC%98%A4%EC%9D%BC%EB%9F%AC_%ED%94%BC_%ED%95%A8%EC%88%98

 

오일러 피 함수 - 위키백과, 우리 모두의 백과사전

오일러 피 함수의 그래프. ϕ(1)부터 ϕ(1000)까지의 값들을 나타낸다. 수론에서 오일러 피 함수(-函數, 영어: Euler’s phi (totient) function)는 정수환의 몫환의 가역원을 세는 함수이다. 즉, n이 양의 정

ko.wikipedia.org

GCD(n,k) = 1 는 n과 k가 서로수임을 의미하는 것이고, n과 서로소인 정수의 갯수를 세는 방법은 정수론에서 오일러 피 함수가 있다. 

오일러 피 함수를 간략히 설명하면 다음과 같다. 오일러 피 함수는 주어진 n의 소인수를 구한 뒤에, 각 소인수들의 (1-1/p)를 구해 n에 곱해주면 서로소의 갯수를 구할 수 있다. 따라서 이 함수를 python으로 구현하여 다음과 같이 계산하도록 한다.

1
2
3
4
5
6
7
8
9
10
= int(input())
answer = n
for i in range(2int(n**0.5)+1):
    if n%i==0:
        while n%i==0:
            n //= i
        answer *= ((i-1)/(i))
if n > 1:
    answer *= 1 - (1 / n)
print(int(answer))
cs

문제링크:

https://www.acmicpc.net/problem/11689

 

11689번: GCD(n, k) = 1

자연수 n이 주어졌을 때, GCD(n, k) = 1을 만족하는 자연수 1 ≤ k ≤ n 의 개수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]10164. 격자상의 경로  (0) 2022.02.22
[BOJ]1916. 최소비용 구하기  (0) 2022.02.18
[BOJ]2526. 싸이클  (0) 2022.02.14
[BOJ]2641. 다각형그리기  (0) 2022.02.11
[BOJ]2660. 회장뽑기  (0) 2022.02.10

문제:

두 자연수 N과 P를 가지고  다음 과정을 거쳐서 나오는 숫자들을 차례대로 출력해보자. 처음 출력하는 숫자는 N이고, 두 번째 이후 출력하는  숫자들은 N을 곱하고 P로 나눈 나머지를 구하는 과정을 반복하여 구한다. 즉, 먼저 N에 N을 곱하고, 이 수를 P로 나눈 나머지를 두 번째에 출력한다. 다음에는 이 나머지에 N을 곱하고 P로 나눈 나머지를 출력한다. 다음에는 이 나머지에 N을 곱한 후 P로 나눈 나머지를 출력한다. 이 과정을 계속 반복해보면 출력되는 숫자들에는 반복되는 부분이 있다.

예를 들어서, N=67, P=31인 경우를 생각해보자. 처음 출력되는 숫자는 67이고, 두 번째로 출력되는 숫자는 67×67 = 4489를 31로 나눈 나머지 25이다. 다음에는 25×67 = 1675를 31로 나눈 나머지 1, 다음에는 1×67 = 67을 31로 나눈 나머지 5가 차례대로 출력된다. 다음에는 5×67 = 335를 31로 나눈 나머지 25가 출력되는데, 이 수는 이미 이전에 출력된 수이다. 이 과정을 그림으로 보이면 다음과 같다.

즉 이 과정을 반복하면, 처음 67을 제외하면 3개의 숫자 25, 1, 5가 계속 무한히 반복되게 된다.   또 다른 예로, N=9, P=3을 가지고 시작하면, 9×9 = 81이고 3으로 나눈 나머지는 0이며, 0×3 = 0이고 3으로 나눈 나머지도 0이기 때문에 처음 9를 제외하면 0이 무한히 반복되게 된다. 

N과 P를 입력받아 위와 같이 정의된 연산을 수행하였을 때,  반복되는 부분에 포함된 서로 다른 숫자의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 처음 시작하는 N과 P가 공백을 사이에 두고 주어진다. 단, 1 ≤ N ≤ 1,000, 2 ≤ P ≤ 97이다.  

출력:

첫째 줄에 반복되는 부분에 포함된 서로 다른 숫자의 개수를 출력한다.

풀이방법:

 while 반복문을 사용하여, 주어진 조건에 따라 계속해서 연산을 진행하다가 memory에 같은 같이 존재하면 반복문을 종료하는 방식으로 문제를 해결한다. 이 때, 싸이클이 반드시 처음 시작한 숫자로부터 시작되는 것이 아니기 때문에 종료된 숫자가 있는 인덱스를 찾아서 전체 memory에서 빼줌으로써 싸이클의 길이를 계산한다.

1
2
3
4
5
6
7
8
9
10
n, p = map(int,input().split())
memory = []
next_ = n
while True:
    next_ = (next_*n) % p
    if next_ in memory:
        break
    else:
        memory.append(next_)
print(len(memory)-memory.index(next_))
cs

문제링크:

https://www.acmicpc.net/problem/2526

 

2526번: 싸이클

두 자연수 N과 P를 가지고  다음 과정을 거쳐서 나오는 숫자들을 차례대로 출력해보자. 처음 출력하는 숫자는 N이고, 두 번째 이후 출력하는  숫자들은 N을 곱하고 P로 나눈 나머지를 구하는 과

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1916. 최소비용 구하기  (0) 2022.02.18
[BOJ]11689. GCD(n,k) = 1  (0) 2022.02.16
[BOJ]2641. 다각형그리기  (0) 2022.02.11
[BOJ]2660. 회장뽑기  (0) 2022.02.10
[BOJ]10827. a^b  (0) 2022.02.09

문제:

모눈종이에 다각형을 그리려고 한다. 그리는 방법은 모양수열로 표시된다. 모양수열은 1과 4사이의 숫자가 연속되어 나열된 것으로 1은 오른쪽으로, 2는 위쪽으로, 3은 왼쪽으로, 4는 아래쪽으로 한 칸씩 그리는 것을 말한다.

예를 들어 아래 그림의 다각형 (2)는 점 A에서 시작하여 화살표 방향으로 모양수열 1411433322를 따라서 그린 것이다. 다각형 (3)은 점 B에서 시작하여 화살표 방향으로 모양수열 3221411433을 따라서 그린 것이다. 또한 다각형(4)는 점 C에서 시작하여 화살표 방향으로 모양수열 4411123323을 따라서 그린 것이다. 다각형 (2), (3), (4)는 다각형 (1)과 같으므로 모양수열들 1411433322, 3221411433, 4411123323은 모두 같은 다각형을 그릴 수 있다. 단, 다각형이 회전된 것이나 뒤집어진 것은 같은 다각형이 아니다. 그러므로 아래 그림의 다각형 (5)와 (6)은 다각형 (1)과 다르다.

한 개의 표본 모양수열과 여러 모양수열들이 주어졌을 때 표본 모양수열과 같은 다각형을 그릴 수 있는 모양수열들을 모두 찾는 프로그램을 작성하시오.

입력:

첫째 줄에는 표본 모양수열의 길이(숫자의 개수)가 주어지고, 둘째 줄에는 표본 모양수열이 주어진다. 셋째 줄에는 모양수열의 개수가 주어지고 넷째 줄부터는 각 줄에 표본 모양수열과 같은 길이의 모양수열이 하나씩 주어진다. 단, 모양수열들의 개수는 최대 100 개이고 모양수열의 길이는 최대 50 이다. 모양수열의 각 숫자 사이에는 빈칸이 하나 있다.

출력:

첫째 줄에는 입력된 표본 모양수열과 같은 다각형을 그리는 모양수열들의 개수를 출력한다. 둘째 줄부터는 각 줄에 표본 모양수열과 같은 다각형을 그릴 수 있는 모양수열을 출력한다. 출력되는 모양수열의 숫자들은 한 칸 띄고 출력한다.

풀이방법:

발생할 수 있는 경우의 수는 크게 두 가지다. 첫번째는 시계방향으로 진행하는 방법, 혹은 반시계방향으로 진행하는 방법이다.

따라서 주어진 표본 모양수열이 있으면 그 모양을 반대로 진행시킨 것을 생성하고, 각각 deque의 rotate 기능을 사용하여 회전시켜서 모든 경우의 수를 만든다. 그리고 주어진 입력이 이 경우의 수에 존재한다면 출력하고, 그렇지 않다면 넘어가도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from collections import deque
 
dx = [1,0,-1,0]
dy = [0,1,0,-1]
= int(input())
standard = list(map(int,input().split()))
standard = deque(standard)
reversed_s = []
for s in standard:
    if s==1:
        r = 3
    elif s==2:
        r = 4
    elif s==3:
        r = 1
    elif s==4:
        r = 2
    reversed_s.append(r)
 
reversed_s.reverse()
reversed_s = deque(reversed_s)
candidate = []
while n:
    standard.rotate(1)
    reversed_s.rotate(1)
    n-=1
    candidate.append(list(standard))
    candidate.append(list(reversed_s))
 
answer = []
= int(input())
for _ in range(m):
    s = list(map(int,input().split()))
    if s in candidate:
        answer.append(s)
print(len(answer))
for a in answer:
    print(*a)
cs

문제링크:

https://www.acmicpc.net/problem/2641

 

2641번: 다각형그리기

모눈종이에 다각형을 그리려고 한다. 그리는 방법은 모양수열로 표시된다. 모양수열은 1과 4사이의 숫자가 연속되어 나열된 것으로 1은 오른쪽으로, 2는 위쪽으로, 3은 왼쪽으로, 4는 아래쪽으로

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]11689. GCD(n,k) = 1  (0) 2022.02.16
[BOJ]2526. 싸이클  (0) 2022.02.14
[BOJ]2660. 회장뽑기  (0) 2022.02.10
[BOJ]10827. a^b  (0) 2022.02.09
[BOJ]2631. 줄세우기  (0) 2022.02.08

문제:

월드컵 축구의 응원을 위한 모임에서 회장을 선출하려고 한다. 이 모임은 만들어진지 얼마 되지 않았기 때문에 회원 사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 모두가 서로 알 수 있다. 각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게 된다.

예를 들어 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나 친구의 친구임을 말한다. 또한 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다.

4점, 5점 등은 같은 방법으로 정해진다. 각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다.

회장은 회원들 중에서 점수가 가장 작은 사람이 된다. 회장의 점수와 회장이 될 수 있는 모든 사람을 찾는 프로그램을 작성하시오.

입력:

입력의 첫째 줄에는 회원의 수가 있다. 단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터 회원의 수만큼 붙어 있다. 마지막 줄에는 -1이 두 개 들어있다.

출력:

첫째 줄에는 회장 후보의 점수와 후보의 수를 출력하고, 두 번째 줄에는 회장 후보를 오름차순으로 모두 출력한다.

풀이방법:

'친구사이'라는 용어가 애매하게 정의되어 있어서 헷갈릴 수 있지만 자신을 제외한 다른 모든 회원과 친구가 되기 위해 필요한 최대 거리를 의미한다. 즉 '친구의 친구의 친구'는 그 사람과 내가 알기 위해서 필요한 다리의 수와 같다.

따라서 이 문제를 플로이드-와샬문제로 생각하여 해결한다. 플로이드-와샬로 친구가 되기 위해 필요한 사람의 수들을 모두 구한 뒤, 각 사람마다 제일 큰 값이 그 회원의 점수가 된다.

회장이 될 수 있는 사람은 그 점수들 중 가장 작은 사람이여야 하기 때문에 그 점수들 중에 min을 찾은 후 그 점수를 가지고 있는 사람들을 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
= int(input())
INF = float('inf')
arr = [[INF for _ in range(N+1)] for _ in range(N+1)]
for i in range(1,N+1):
    arr[i][i] = 0
 
while True:
    a,b = map(int,input().split())
    if a==-1 and b==-1:
        break
    arr[a][b] = 1
    arr[b][a] = 1
    
for k in range(1,N+1):
    for i in range(1,N+1):
        for j in range(1,N+1):
            if arr[i][j] > arr[i][k] + arr[k][j]:
                arr[i][j] = arr[i][k] + arr[k][j]
score = []
for i in range(1,N+1):
    score.append(max(arr[i][1:]))
ans_score = min(score)
candiate_n = score.count(ans_score)
print(ans_score, candiate_n)
print(*[i+1 for i in range(N) if ans_score==score[i]])
cs

문제링크:

https://www.acmicpc.net/problem/2660

 

2660번: 회장뽑기

입력의 첫째 줄에는 회원의 수가 있다. 단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2526. 싸이클  (0) 2022.02.14
[BOJ]2641. 다각형그리기  (0) 2022.02.11
[BOJ]10827. a^b  (0) 2022.02.09
[BOJ]2631. 줄세우기  (0) 2022.02.08
[BOJ] 9576. 책 나눠주기  (0) 2022.02.07

+ Recent posts