일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 투포인터
- LazyPropagation
- DP
- MST
- 다익스트라
- DisjointSet
- 비트마스크
- BFS
- 위상정렬
- 에라토스테네스의 체
- 플로이드와샬
- lis
- lca
- 삼분탐색
- 구현
- 브루트포스
- 정렬
- 누적합
- 크루스칼
- 세그먼트트리
- 펜윅트리
- 이분탐색
- 수학
- boj
- 이분매칭
- 백준
- dfs
- 이진탐색
- 그리디
- 좌표압축
Archives
- Today
- Total
lastknight00
[백준]36진수(1036) 본문
문제 링크 : [백준]36진수(1036)
문제 설명
N개의 36진수가 주어졌을 떄, K개의 숫자를 Z(10진수로 35)로 바꾸었을 때 가능한 최대값을 출력하세요.
입력
N(수열의 갯수, 1 <= N <= 50)
Vi(36진수(최대 50자리))
K(변경할 수 있는 숫자의 갯수, 0 <= K <= 36)
5
GOOD
LUCK
AND
HAVE
FUN
7
출력
31YUB
카테고리
#정렬 #큰수 #그리디
시간 복잡도 상한
O(N!), O(K!) 만 아니면 될거 같아요??
해결 방법
- 자리수가 50자리이고, 거기다 36진수이기 때문에 언어에서 제공하는 자료형으로는 어렵습니다.
- 따라서 36진수 덧셈을 먼저 구현해야 합니다.
- 큰 수는 문자열로 처리해야 하며, 입력받은 값을 거꾸로 뒤집어야 자리수를 맞추는 번거로움을 줄일 수 있습니다.
3-1. 예시)ABC + ABCD 로 주어졌을 때, 그대로 연산하게 되면, 두 문자열의 자리수를 구하여, 첫번째 수의 맨 앞자리에 패딩을 넣어 자리수를 맞추어야 하지만, 두 수를 거꾸로 뒤집어, CBA + DCBA로 하면, 인덱스 보정없이 바로 계산이 가능합니다. - 거꾸로 저장을 하였다면, 각 인덱스마다 두 수를 더하면 됩니다.
- 하지만 덧셈에는 자리 올림이 발생하니 그것도 처리를 해주면 됩니다.
- 여기까지는 귀찮기는 하지만 어려운 것을 없을 것입니다.
- 문제는 여기부터!! 36진수(0~Z)중 K개의 수를 Z로 바꾸는 모든 경우 중 최대값을 구해야 합니다.
- 모든 주어진 수에서 나타난 각각의 수를 따로 저장합니다.
8-1. 123 + 312 + 523 이라고 한다면,
8-2. 1은 100 + 10 = 110
8-3. 2는 20 + 2 + 20 = 42
8-4. 3은 3 + 300 + 3 = 306
8-5. 요렇게 저장합니다.
8-6. 하지만 사실 나중을 위하여, 1을 예로 들면, Z00 - 100 + Z0 - 10 으로 계산합니다.
8-7. 현재 숫자를 Z로 바꿨을 때 얻을 수 있는 이득을 계산합니다. - 각 숫자별로 그 수를 Z로 바꾸었을 때 얻을 수 있는 이득들이 모두 계산되었습니다.
- 이 중 K개를 골라 최대값을 만들려면 이득이 최대로 되는 K개를 구하면 됩니다.
- 즉 이득으로 내림차순으로 정렬하여, 6까지에서 구한 값에다가 K개의 수를 바꿈으로써 얻을 수 있는 이득을 더해줍니다.
시간복잡도
O(N)
코드
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m,d[60],i,j,l;
struct E{
int s[60];
bool operator <(const E &a)const{
for(int i=59;i>=0;i--){
if(s[i]>a.s[i])return true;
if(s[i]<a.s[i])return false;
}
return false;
}
}e[36];
char s[51],t;
int main(){
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",s);
l=strlen(s);
for(j=0;j<l;j++){
t=s[l-j-1];
if(t<'A'){
d[j]+=t-'0';
e[t-'0'].s[j]+=('9'-t+26);
}else{
d[j]+=t-'A'+10;
e[t-'A'+10].s[j]+=('Z'-t);
}
}
}
scanf("%d",&m);
for(i=0;i<59;i++){
d[i+1]+=d[i]/36;
d[i]%=36;
for(j=0;j<36;j++){
e[j].s[i+1]+=e[j].s[i]/36;
e[j].s[i]%=36;
}
}
sort(e,e+36);
for(l=i=0;i<59;i++){
for(j=0;j<m;j++)d[i]+=e[j].s[i];
d[i+1]+=d[i]/36;
d[i]%=36;
if(d[i])l=i;
}
for(;l>=0;l--)printf("%c",d[l]>9?d[l]-10+'A':'0'+d[l]);
}
'PS' 카테고리의 다른 글
[백준]배열에서 이동(1981) (0) | 2020.07.14 |
---|---|
[백준]백양로 브레이크(11562) (0) | 2020.07.13 |
[백준]연속합 2(13398) (0) | 2020.07.10 |
[백준]통나무 자르기(1114) (0) | 2020.07.06 |
[백준]한조 대기 중(14433) (0) | 2020.07.05 |
Comments