[9번째 Contest]
슬럼프 시기에 친 버추얼,, A도 못 풀고 빡종. 지금 다시 보니까 이땐 많이 힘들었나보다. A도 못 풀고,,
정수 , , 를 입력 받는다. 은 문자열 의 갯수, 는 문자열 의 갯수다. 개와 개를 적절히 배치해서 길이가 인 문자열을 만들어라. 단, 연속된 R의 갯수를 최소화해라.
문자열 하나를 기준으로 사이 공간과 양끝에 문자열 을 균등하게 배치하면 된다. 이 배치될 공간은 개 있다. 각 공간에 개를 배치하고 남은 건 하나씩 배치하면 된다.
def solve():
n, a, b = map(int, input().split())
ans = ''
b += 1
for i in range(a%b):
ans += 'R'*(a//b+1)+'B'
for i in range(b-a%b):
ans += 'R'*(a//b)+'B'
print(ans[:-1])
for __ in range(int(input())):
solve()
길이가 인 과 로 구성된 이 주어진다. 정확히 번 다음 작업을 하고 난 뒤에 만들 수 있는 문자열 중 사전 순으로 가장 뒷 문자열을 구하라. 즉, 가장 큰 수를 구하라.
번째 비트를 고르고 번째를 제외한 나머지 비트를 모두 뒤집는다.
그리고 각 비트 별로 작업을 수행한 횟수를 구해라.
일반적인 풀이
다른 풀이: 미시적 접근
내 풀이 방식인데, 이런 애드혹스러운 문제에선 이런 접근이 필요한 경우가 있다.
번 비트와 번 비트에 대해 작업을 수행하면, 두 비트만 뒤집힌다. 번의 작업으로 다음 작업을 할 수 있는데, 이걸 응용해서 풀 수 있다.
이고 이라고 하자. 번의 작업으로 로 만들 수 있다. 앞에서부터 인 비트를 개씩 로 바꿔주면 된다.
여기서 가 홀수, 짝수에 따라 결과가 바뀐다. 가 홀수라면, 위 작업을 아무리 반복해도 항상 한 번의 작업 횟수가 남는다. 그러면 번 비트를 제외한 모든 비트를 뒤집는 작업을 하게 된다.
가 홀수라면, 문자열을 최대한 으로 바꾸고 마지막에 모두 뒤집어 주면 된다. 문자열 앞에서부터 인 를 골라서 으로 바꾼다. 마지막에 가장 앞선 을 선택하고 작업을 회 수행하면 된다.
가 짝수라면, 문자열을 최대한 로 바꾸면 된다. 만약에 작업 횟수가 남았는데, 가장 앞선 가 이 아니라면, 에 대해 작업을 2회 더 실행한다. 즉, 작업 횟수가 남았는데 값이 인 비트가 양끝이 아닌 곳이 있다면, 맨 오른쪽 값과 바꾼다.
남은 작업 횟수는 반드시 짝수고, 이는 결과에 어떤 영향을 주지 못한다. 남은 작업 횟수를 맨 앞에 더해준다.
# 다른 풀이: 미시적 접근
def solve():
n, k = map(int, input().split())
s = list(map(int, list(input())))
a, b = [], []
cnt = [0]*n
for i in range(n):
if s[i]:
b.append(i)
else:
a.append(i)
if k%2:
for i in range(0, len(b)-1, 2):
if k<2:
break
s[b[i]], s[b[i+1]] = 0, 0
cnt[b[i]] += 1
cnt[b[i+1]] += 1
k -= 2
for i in range(n):
if s[i]==1:
s = [int(not x) for x in s]
s[i] = 1
cnt[i] = 1
k -= 1
break
else:
s = [int(not x) for x in s]
s[-1] = 0
cnt[-1] += 1
k -= 1
else:
for i in range(0, len(a)-1, 2):
if k<2:
break
s[a[i]], s[a[i+1]] = 1, 1
cnt[a[i]] += 1
cnt[a[i+1]] += 1
k -= 2
if k:
for i in range(n-1):
if s[i]==0:
s[i], s[-1] = 1, 0
cnt[i] += 1
cnt[-1] += 1
k -= 2
break
cnt[0] += k
print(''.join(map(str, s)))
print(*cnt)
for __ in range(int(input())):
solve()