A. Candies and Two Sisters

문제

https://drive.google.com/open?id=1rrQnFbRs9gyRPFOKbxJQKA1laW9Aj7Qj

예를들어, 10이 있으면 이 10을 두개로 쪼개는 방법의 개수에 대한 문제이다. [1, 9], [2, 8], [3, 7], [4, 5] 까지. 왼쪽 < 오른쪽 이어야 하기 때문에 [5, 5] 부터는 적용이 안된다. 그리고 왼쪽 오른쪽 모두 1 이상이다.

예시

[input]
6
7
1
2
3
2000000000
763243547

[output]
3
0
0
1
999999999
381621773

답1 – 이곳을 클릭하면 정답이 보입니다
def answer(n) :
  if n%2 == 0 :
    return int((n/2)-1)
  else :
    return int((n-1)/2)
    
testCount = int(input())
for _ in range(testCount) :
  n = int(input())
  print(answer(n))
답2 – 이곳을 클릭하면 정답이 보입니다
def answer(n) :
  if n%2 == 0 :
    return (n//2)-1
  else :
    return n//2
    
testCount = int(input())
for _ in range(testCount) :
  n = int(input())
  print(answer(n))

그러고 보니 어차피 //연산을 쓰면 소수점 이하는 버려지니까 n이 홀수일 경우에 코드가 더 심플해지네

B. Construct the String

문제

https://drive.google.com/open?id=1KDh3TcYPhk9BY7mBCp5BXJ_bEzp8R-KO

  • 길이가 n인 문자열 s를 만들어야 한다.
  • (a와 b가 주어지는데) a만큼의 길이의 s의 substring들이 b만큼의 유니크한 문자들을 포함해야한다.

예시

[input]
4
7 5 3
6 1 1
6 6 1
5 2 2

[output]
tleelte
qwerty
vvvvvv
abcde

n = 7, a = 5, b = 3인 경우에

답1 – 여기를 클릭하면 정답이 보입니다
def answer(n, a, b) :
  alpha = "abcdefghijklmnopqrstuvwxyz"
  loop = alpha[0:b]
  if a//len(loop) >= 1 :
    temp = loop
    loop = loop*(a//len(loop))
    loop += "".join([temp[i] for i in range(0, a%len(temp))])
  else :
    loop += "".join([loop[i] for i in range(0, a-len(loop))])
  
  s = ''
  if n//len(loop) >= 1 :
    s = loop*(n//len(loop))
  
  return s + "".join([loop[i] for i in range(0, n%len(loop))])
testCount = int(input())
for _ in range(testCount) :
  n, a, b = map(int, input().split())
  print(answer(n, a, b))

b만큼 짜른게 a안에 반복되어 있어야하고, 또 그렇게 만들어진 a만큼의 substring이 n안에 반복되어 있어야 한다.

3만큼 짜른게(abc) 5안에 반복되어 있으려면, 먼저 5를 3으로 나눈것의 몫을 구하고 나머지를 또 뒤에 붙여줘야한다. 그러면 abcab가 된다. 이게 또 13안에 반복되어 나타나야 하기 때문에 13을 5를 나눈 몫만큼 반복해서 붙여주고 나머지값인 3만큼 abcab에서 짤라서 뒤에 또 붙여주면 된다. 그러면 abcababcababc가 된다. 이거를 왼쪽에서부터 5개씩 짤라도 그 substring의 구성요소는 a,b,c로만 이루어져있다.

답2 – 여기를 클릭하면 정답이 보입니다
def answer(n, a, b) :
  alpha="abcdefghijklmnopqrstuvwxyz"
  c=n//b
  d=n%b
  return (c*alpha[0:b]+alpha[0:d])
testCount = int(input())
for _ in range(testCount) :
  n, a, b = map(int, input().split())
  print(answer(n, a, b))

재미있는 사실은 b <= a이기만 하다면 a가 얼마가 되었든 간에(=어떻게 잘라도) 그 안에는 b만큼의 각기 다른 문자가 있다. 즉! ab로 먼저 체운다음에 na로 체우는 방식이 아니라, 그냥 곧바로 nb로 체워도 된다. 가령, n이 13이고 b가 3일때, abcabcabcabca 를 만들면 a가 3이든 4이든 5이든 6이든 간에 그 안은 모두 abc로만 이루어져있다.

C. Two Teams Composing

문제

https://drive.google.com/open?id=1Kx6XF1AeEMn4Ras-0w6K9ubfqw2jnLLz

어떤 배열이 주어지는데 그 배열의 subset 2개를 골라야한다.
다만, 조건은 아래와 같다.

  1. 왼쪽과 오른쪽 배열의 사이즈는 같아야한다
  2. 왼쪽 배열안의 숫자들은 모두 달라야한다
  3. 오른쪽 배열안의 숫자들은 모두 같아야한다

자, 이런 조건을 만족하는 팀분배의 다양한 경우의 수가 있을텐데, 그때 배열의 크기가 가장 커지도록하는 경우가 있을거다. 그때의 배열의 크기(x)를 구하는게 문제이다.

예시

[input]
4
7
4 2 4 1 4 3 4
5
2 1 5 4 3
1
1
4
1 1 1 3

[output]
3
1
0
2

4 2 4 1 4 3 같은 경우에는, 꼭 3:3으로 나눌 필요가 없고 2:2, 1:1도 되니까 아래처럼 2팀으로 나눌 수 있다.

  1. [2] : [4]
  2. [1] : [4]
  3. [1, 2] : [4, 4]
  4. [1, 2, 3] : [4, 4, 4]

이중에서 배열의 길이가 가장 긴거는 4번이고 그 길이는 3이다. 그래서 답이 3이다.

답1 – 여기를 클릭하면 정답이 보입니다
def answer(students) :
    _max = {
        'studentKey' : 0,
        'duplicatedSkill' : 0
    }
    dic = {}
    for i in range(len(students)) :
        key = "_"+str(students[i])
        if dic.get(key) is not None :
            dic[key] += 1
        else :
            dic[key] = 1
        
        if dic[key] > _max['duplicatedSkill'] :
            _max['duplicatedSkill'] = dic[key]
            _max['studentKey'] = key

    leftTeamLength = 0
    for k, v in dic.items() :
        if k != _max['studentKey'] :
            leftTeamLength += 1

    # 1 1 1 3 인경우에는 [1, 3] vs [1, 1] 이렇게 될 수 있잖아
    # 다만 이거는 2 이상 차이가 나야 쓸수있다.
    # 22222233145
    # [1, 3, 4, 5, 2] vs [2, 2, 2, 2, 2]
    # 어차피 위에서 key가 다를때 leftTeamLength를 1씩 늘린거니까, 절대로 2가 이미 있을일은 없다. 
    if _max['duplicatedSkill'] - leftTeamLength > 1 :
        leftTeamLength += 1

    if leftTeamLength > _max['duplicatedSkill'] :
        return _max['duplicatedSkill']

    return leftTeamLength
답2 – 여기를 클릭하면 정답이 보입니다
from collections import Counter

def answer(students) :
    li = Counter(students)
    maxDuplicatedSkill = max(li.values())
    studentKeys = (li.keys())
    if(maxDuplicatedSkill >= len(studentKeys)) :
	    return min(maxDuplicatedSkill-1, len(studentKeys))
    return maxDuplicatedSkill

testCount = int(input())
for _ in range(testCount) :
    n = int(input())
    students = list(map(int, input().split()))
    print(answer(students))

정답 1이랑 개념은 같은데 코드가 더 유려하다.

우선은 Counter를 써줌으로써 위처럼 key = "_"+str(student[i])같은 코드가 필요 없고, max(li.values())로 중복된값중 가장 큰거를 쉽게 구했다. 또한 [1, 3] vs [1, 1] 같은 경우와 [1, 2, 3, 4] vs [4, 4, 4, 4, 4, 4] 같은 경우도 min(maxDuplicatedSkill-1, len(studentKeys))으로 쉽게 처리했다. maxDuplicatedSkill-1 이거는 왼쪽팀에 중복된 4를 하나 줘버린다는 의미이다.

D. Anti-Sudoku

문제

완성된 sudoku가 주어지는데, 그중에서 최대 9개의 숫자를 다른 숫자로 바꿔서 anti-sudoku로 만들어야한다. anti-sudoku란 다음을 의미한다.

  1. 숫자는 1~9사이이다. (당연한소리)
  2. 각행은 최소 2개의 같은 숫자를 갖고있다.
  3. 각열은 최소 2개의 같은 숫자를 갖고있다.
  4. 모든 3 X 3블럭은 최소 2개의 동일한 원소를 갖고있다.

그렇게 숫자 (최대) 9개를 바꾼 그 anti-sudoku를 출력하면된다.

예시

[input]
1
154873296
386592714
729641835
863725149
975314628
412968357
631457982
598236471
247189563

[output]
154873396
336592714
729645835
863725145
979314628
412958357
631457992
998236471
247789563