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

 

15736번: 청기 백기

예제 입력 1의 경우 1, 2, 3번 깃발이 존재하고, 3명의 선수가 참가한다. 첫 번째 선수는 1의 배수의 번호를 가진 깃발을 뒤집는다. 초기에 청색이였던 깃발은 첫 번째 선수에 의해 모두 백기로 된

www.acmicpc.net

문제

소프트웨어융합대학 학생회에서 주최한 소융체전에서 청기 백기 뒤집기 게임이 한창이다. 소프트웨어학부, ICT융합학부가 번갈아가면서 게임을 진행하는 중이다. 게임의 규칙은 간단하다. 게임을 진행할 차례인 학부에서 출전한 선수들 N명이 존재한다. 학생들의 앞 탁자에는 N개의 깃발이 청색이 위로 백색이 아래로 보이도록 놓여있다. 이때 출전한 선수 중 첫 번째 선수는 N개의 깃발 중 1의 배수에 해당하는 번호의 깃발을 뒤집어 놓는다. 다음 두 번째 선수는 N개의 깃발 중 2의 배수에 해당하는 번호의 깃발을 뒤집어 놓는다. i 번째 선수는 i의 배수에 해당하는 번호의 깃발을 뒤집고, N 번째 선수까지 진행하면 끝이 난다. 그렇다면 이 게임에서 N 명의 선수가 참가하고 N개의 깃발이 존재할 때, N 번째 선수까지 진행하여 완료된 상태에서 백색이 위로 놓여있는 깃발의 수가 몇 개인지 알아보자.

입력

첫 번째 줄에 출전한 학생의 수이자, 깃발의 개수인 N(1 ≤ N ≤ 2,100,000,000)이 주어진다.

출력

첫 번째 줄에 N 번째 선수까지 진행한 후의 상태의 깃발 중 백색이 위로 놓여있는 깃발의 수를 출력한다.

예제 입력 1 복사

3

예제 출력 1 복사

1

예제 입력 2 복사

24

예제 출력 2 복사

4

 

문제풀이(1)

모든 깃발이 위가 청색일 때, N명의 사람이 i배수 만큼 뒤집게된다. 이때, 해당 번호의 약수가 홀수 인것은 백기가 된다.
백기의 개수를 구하는 문제이기 때문에 해당 번호의 약수가 홀수인 것을 찾으면 될 것이다.
1 = 1번 = 백기, 2 = 2번 = 청기, 3 = 2번 = 청기, 4 = 3번 = 백기 ...
루트 i 가 정수일 때, 약수가 홀수로 나오게 된다.
시간제한이 1초이고, N은 최대 21억 번이기 때문에 일반적인 반복문을 순회할 경우 21초 걸리게된다.
그렇기 때문에 루트 i가 N보다 작을 경우를 카운트 해주면 된다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const N = Number(require("fs").readFileSync(filePath).toString().trim());

// 1 = 백기, 2 = 청기기 때문에 초기 값을 1로 둔다.
let answer = 1;

for (let i = 2; i * i <= N; i++) {
  answer++;
}

console.log(answer);

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

 

11507번: 카드셋트

예제1 : 12 12 11 13은 잃어버린 P카드 :  12개, K : 12개, H : 11개, T : 13라는 뜻이다. 예제2 : 같은 카드(H02)가 존재하므로 GRESKA을 출력하였다.

www.acmicpc.net

문제

최근에 진솔이는 로봇 공학을 하기 시작했다. 그래서 포커 카드가 완전한 세트인지 확인하는 로봇을 만들기로 결심했다.

그는 프로그램을 작성하는 일을 분담했다. 그 프로그램은 카드의 모양(스페이드(♠), 하트(♡), 다이아몬드(♢), 클럽(♣))을 인식하는 것이다. 문제를 간단하게 하기 위해서 모든 카드는 하나의 모양과 하나의 숫자를 가진다고 가정한다.

여기서 그 모양은 실제 그림 대신 문자로 대체한다. P,K,H,T에 해당한다. 그리고 숫자는 1~13에 해당하는 정수이다. 로봇은 각각의 카드를 TXY의 형태로 '카드 이름'을 정하는데 T는 모양에 해당하고 XY는 숫자에 해당한다. 만약 만약 숫자가 1자리 숫자이면 X=0에 해당한다. ex) 01.

만약에 모양이 P이고 숫자가 9이면 P09이다.

완벽한 카드 한 세트는 52개로 이루어져 있다. (4 (모양)x 13(숫자))

로봇은 모든 카드의 '카드이름'을 읽고 문자열 S로 결합한다.

이제 진솔이가 프로그래밍 하는 것을 도와주자.  문자열을 읽어 얼마나 많은 카드를 잃어버렸는지 세면 된다.

만약에 2개의 같은 카드가 존재한다면 GRESKA이라고 출력하면 된다.

입력

오직 1줄만 문자열 S(1 ≤ |S| ≤ 1000)가 들어온다. 이것은 현재 가지고 있는 카드 이름에 해당한다.

출력

만약 똑같은 카드가 존재한다면 GRESKA을 출력한다.

그렇지 않으면 4개의 정수를 공백 문자로 구분하여 출력한다. 각각 P, K, H, T에 해당한다.

예제 입력 1 복사

P01K02H03H04

예제 출력 1 복사

12 12 11 13

예제 입력 2 복사

H02H10P11H02

예제 출력 2 복사

GRESKA

 

문제풀이(1) - 런타임 에러

P, K, H, T의 카드가 각 13개씩 존재하는데 입력에 중복되지 않은 각 카드의 종류별로 개수를 세어주면 될 것이다.
1. 3자리씩 끊어서 카드의 총 개수를 파악한다.
2. 카드의 총 개수 중 중복여부를 확인한다. (중복일 경우 'GRESKA' 출력)
3. 카드 종류별로 13-가지고 있는 카드수 를 계산한뒤 출력한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = require("fs").readFileSync(filePath).toString().trim();

// 전체 카드 목록
const totalCardList = [];
// 중복된 카드 여부
let flag = false;

// 카드 등록
for (let i = 0; i < input.length; i += 3) {
  const card = input.slice(i, i + 3);

  if (!totalCardList.includes(card)) {
    totalCardList.push(card);
  } else {
    flag = true;
    break;
  }
}

if (flag) {
  console.log("GRESKA");
} else {
  const answer = { P: 13, K: 13, H: 13, T: 13 };
  for (let i = 0; i < totalCardList.length; i++) {
    answer[totalCardList[i][0]] -= 1;
  }
  console.log(Object.values(answer).join(" ").trim());
}

 

문제풀이(2)

문제풀이(1)도 문제는 풀렸지만 입력단계에서 런타임 에러가 발생하는 문제였다.
입력을 readline으로 변경하니 해결되었다.

const readline = require("readline");
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// 전체 카드 목록
const totalCardList = [];
// 중복된 카드 여부
let flag = false;

rl.on("line", function (line) {
  const input = line.trim();

  // 카드 등록
  for (let i = 0; i < input.length; i += 3) {
    const card = input.slice(i, i + 3);

    if (!totalCardList.includes(card)) {
      totalCardList.push(card);
    } else {
      flag = true;
      break;
    }
  }

  if (flag) {
    console.log("GRESKA");
  } else {
    const answer = { P: 13, K: 13, H: 13, T: 13 };
    for (let i = 0; i < totalCardList.length; i++) {
      answer[totalCardList[i][0]] -= 1;
    }
    console.log(Object.values(answer).join(" ").trim());
  }

  rl.close();
}).on("close", function () {
  process.exit();
});

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

 

12782번: 비트 우정지수

진홍이는 숫자를 좋아한다. 오늘도 숫자를 가지고 놀던 진홍이는 두 숫자의 비트 우정지수를 구해보았다. 비트 우정지수란, 10진법으로 나타낸 두 정수를 이진수로 나타내었을 때, 두 숫자를 같

www.acmicpc.net

문제

진홍이는 숫자를 좋아한다. 오늘도 숫자를 가지고 놀던 진홍이는 두 숫자의 비트 우정지수를 구해보았다. 비트 우정지수란, 10진법으로 나타낸 두 정수를 이진수로 나타내었을 때, 두 숫자를 같게 만드는데 필요한  최소 연산 횟수를 말한다. 연산의 종류는 다음과 같다.

  1. 하나의 이진수에서 임의의 자리의 숫자를 0 또는 1로 바꾼다.
  2. 하나의 이진수에서 서로 다른 자리에 있는 두 숫자의 위치를 바꾼다.

예를 들어, 10진수 11과 12의 비트 우정지수를 구해보자. 11을 이진수로 나타내면 1011이고, 12를 이진수로 나타내면 1100이다. 1011에서 2의 자리를 0으로 바꾸고(1011 -> 1001), 1의 자리와 4의 자리의 숫자를 서로 바꾸면(1001 -> 1100) 1100이 된다. 즉, 1011을 1100으로 바꾸는 최소 연산 횟수는 두 번으로, 11과 12의 비트 우정지수는 2가 된다.

진홍이는 어떤 두 수가 주어졌을 때 두 수의 비트 우정지수를 구하는 프로그램을 만들고 싶다. 하지만, 아쉽게도 진홍이는 프로그래밍에 약해 10진수를 이진수로 바꾸는 것 밖에 하지 못한다. 여러분이 진홍이를 도와 두 수의 비트 우정지수를 구하는 프로그램을 만들어 주자!

입력

입력의 첫 줄에는 테스트 케이스의 개수 T(1 ≤ T ≤ 50)가 주어진다.

각 테스트케이스의 첫 번째 줄에는 두 이진수 N, M이 주어진다. N, M의 자릿수는 1,000,000을 넘지 않으며, 자릿수는 서로 같다.

출력

각 테스트 케이스마다 두 수의 비트 우정지수를 출력한다.

예제 입력 1 복사

3
1011 1100
100101 110100
00110100 10010111

예제 출력 1 복사

2
1
3

 

문제풀이(1)

1011, 1100 두개의 2진수 비트 2개가 있을 때, 1011을 1100으로 바꾸는 최소 연산횟수를 구하는 문제이다.
1011 -> 1001 -> 1100으로 바뀐다고 한다.

2개 비트의 1의 개수를 구하면서 서로 자리가 다른 곳의 개수도 구한뒤 계산하면 된다고 생각했다.
2개 비트의 1의 개수가 같을 경우 (자리가 다른 곳의 개수 / 2)를 해주면 1과 0의 위치만 바꾸기 때문에 정답이 나올 것이다.
2개 비트이 1의 개수가 다를 경우 (자리가 다른 곳의 개수 - 첫번째 비트이 1의 개수 - 두번째 비트의 1의 개수) / 2 + (첫번째 비트이 1의 개수 - 두번째 비트의 1의 개수)를 하게되면,
1과 0의 차이만큼 변환을 해주고 자리를 이동하게 되는 로직이다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const N = Number(input.shift());
const bitArr = input.map((el) => el.split(" "));

const answer = [];

for (let i = 0; i < N; i++) {
  const [firstBit, secondBit] = bitArr[i];

  let firstBitOneCount = 0; // 첫번째 비트의 1의 개수
  let secondBitOneCount = 0; // 두번째 비트의 1의 개수
  let differentLocationCount = 0; // 다른 자리수의 개수

  for (let j = 0; j < firstBit.length; j++) {
    if (firstBit[j] === "1") firstBitOneCount++;

    if (secondBit[j] === "1") secondBitOneCount++;

    if (firstBit[j] !== secondBit[j]) differentLocationCount++;
  }

  if (firstBitOneCount === secondBitOneCount) {
    answer.push(Math.floor(differentLocationCount / 2));
  } else {
    let subtract = Math.abs(firstBitOneCount - secondBitOneCount);
    answer.push(Math.floor((differentLocationCount - subtract) / 2 + subtract));
  }
}

console.log(answer.join("\n"));

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

 

16439번: 치킨치킨치킨

첫 번째 줄에 고리 회원의 수 N (1 ≤ N ≤ 30) 과 치킨 종류의 수 M (3 ≤ M ≤ 30) 이 주어집니다. 두 번째 줄부터 N개의 줄에 각 회원의 치킨 선호도가 주어집니다. i+1번째 줄에는 i번째 회원의 선

www.acmicpc.net

문제

N명의 고리 회원들은 치킨을 주문하고자 합니다.

치킨은 총 M가지 종류가 있고 회원마다 특정 치킨의 선호도가 있습니다. 한 사람의 만족도는 시킨 치킨 중에서 선호도가 가장 큰 값으로 결정됩니다. 진수는 회원들의 만족도의 합이 최대가 되도록 치킨을 주문하고자 합니다.

시키는 치킨의 종류가 많아질수록 치킨을 튀기는 데에 걸리는 시간도 길어지기 때문에 최대 세 가지 종류의 치킨만 시키고자 합니다.

진수를 도와 가능한 만족도의 합의 최댓값을 구해주세요.

입력

첫 번째 줄에 고리 회원의 수 N (1 ≤ N ≤ 30) 과 치킨 종류의 수 M (3 ≤ M ≤ 30) 이 주어집니다.

두 번째 줄부터 N개의 줄에 각 회원의 치킨 선호도가 주어집니다.

i+1번째 줄에는 i번째 회원의 선호도 ai,1, ai,2, ..., ai,M (1 ≤ ai,j ≤ 9) 가 주어집니다.

출력

첫 번째 줄에 고리 회원들의 만족도의 합의 최댓값을 출력합니다.

예제 입력 1 복사

3 5
1 2 3 4 5
5 4 3 2 1
1 2 3 2 1

예제 출력 1 복사

13

예제 입력 2 복사

4 6
1 2 3 4 5 6
6 5 4 3 2 1
3 2 7 9 2 5
4 5 6 3 2 1

예제 출력 2 복사

25

 

문제풀이(1)

치킨의 종류는 3개이며, 치킨 선호도 점수의 최대합을 구하는 문제이다.
아래와 같은 input이 있을 때, 1번 = 6번째 치킨, 점수 6점 | 2번 = 1번째 치킨, 점수 6점 | 3번 = 4번째 치킨, 점수 9점이다.
이때, 4번의 최대값은 6이지만 1, 4, 6번째 치킨 중 가장 선호도 점수가 높은 1번째 치킨의 선호도만 구할 수 있다.
완전탐색을 통해 문제를 풀 수 있다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const [N, M] = input.shift().split(" ").map(Number);
const arr = input.map((el) => el.split(" ").map(Number));

const answer = [];

for (let i = 0; i < M - 2; i++) {
  for (let j = i + 1; j < M - 1; j++) {
    for (let k = j + 1; k < M; k++) {
      let total = 0;

      arr.forEach((el) => {
        total += Math.max(el[i], el[j], el[k]);
      });

      answer.push(total);
    }
  }
}

console.log(Math.max(...answer));

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

 

2799번: 블라인드

첫째 줄에 M과 N이 공백으로 구분해서 주어진다. (1 ≤ M, N ≤ 100) 다음 줄에는 현재 건너편 아파트의 상태가 주어진다. 모든 창문은 문제 설명에 나온 것 처럼 4*4 그리드로 주어진다. 또, 창문과

www.acmicpc.net

문제

봄이 오고 있다. 해는 높이 떠서 환하게 빛나고 있다. 사람들은 햇볕을 가리기 위해 블라인드를 내린다.

상근이는 이웃들이 무엇을 하는지를 염탐하고, 이것에 대해서 뒷담화를 하는 주부이다. 올해는 건너편 아파트에 사는 사람들이 블라인드를 얼마나 내리는지를 조사하려고 한다. 

모든 창문은 4×4 그리드로 나타낼 수 있고, *를 이용해서 블라인드를 나타낸다. 상근이가 볼 수 있는 창문은 다음 5가지 상태 중 하나이다.

건너편 아파트의 한 층에는 N개의 창문이 있고, 총 M층 건물이다. 현재 건너편 아파트의 창문 상태가 주어졌을 때, 위의 5가지 상태가 각각 몇 번 나오는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 M과 N이 공백으로 구분해서 주어진다. (1 ≤ M, N ≤ 100)

다음 줄에는 현재 건너편 아파트의 상태가 주어진다. 모든 창문은 문제 설명에 나온 것 처럼 4*4 그리드로 주어진다. 또, 창문과 창문은 '#'를 이용해서 구분한다. 예제 입력 형식을 참고하면 좋다. 아파트의 정보는 5M+1줄, 각 줄은 5N+1개 글자로 이루어져 있다.

출력

출력은 총 5개 숫자이다. 문제 설명에 나온 순서대로 각 블라인드 타입이 몇 개 있는지를 출력한다. 숫자를 모두 합하면 M*N이 되어야 한다.

예제 입력 1 복사

1 2
###########
#....#****#
#....#****#
#....#....#
#....#....#
###########

예제 출력 1 복사

1 0 1 0 0

예제 입력 2 복사

2 3
################
#****#****#****#
#****#****#****#
#****#....#****#
#....#....#****#
################
#....#****#****#
#....#****#....#
#....#....#....#
#....#....#....#
################

예제 출력 2 복사

1 1 2 1 1

 

문제풀이(1)

....이 몇번째에 나오느냐에 따라 어떤형태의 창문인지 알 수 있다.
반복문을 순회하며 ....이 몇번째에 나오는지 확인한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const [M, N] = input.shift().split(" ").map(Number);

const answer = Array.from({ length: 5 }).fill(0);

// 아파트의 세로 개수
for (let i = 1; i <= M * 5; i += 5) {
  // 아파트의 가로 개수
  for (let j = 1; j <= N * 5; j += 5) {
    if (input[i][j] === ".") {
      answer[0] += 1;
    } else if (input[i + 1][j] === ".") {
      answer[1] += 1;
    } else if (input[i + 2][j] === ".") {
      answer[2] += 1;
    } else if (input[i + 3][j] === ".") {
      answer[3] += 1;
    } else {
      answer[4] += 1;
    }
  }
}

console.log(answer.join(' '));

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

 

9322번: 철벽 보안 알고리즘

소희는 공개키와 개인키 한 쌍으로 보안을 유지하는 것이 매우 불편하다고 생각했다. 그래서 소희는 공개키만을 이용하는 암호화 체계를 개발했다. 이를 "철벽 보안 알고리즘"이라고 부르기로

www.acmicpc.net

문제

소희는 공개키와 개인키 한 쌍으로 보안을 유지하는 것이 매우 불편하다고 생각했다. 그래서 소희는 공개키만을 이용하는 암호화 체계를 개발했다. 이를 "철벽 보안 알고리즘"이라고 부르기로 했다. 알고리즘은 다음과 같다.

한 단어는 1~10개의 대문자(A-Z)들로 이루어진 문자열이다. 한 문장은 공백으로 구분된 단어들로 이루어졌다.

제 1 공개키는 최대 한 번만 사용된 단어들로 되어있다.

제 2 공개키는 제 1 공개키의 단어들을 재배치하여 만들어진다.

평문(암호화 되지 않은 문장)은 제 1 공개키와 같이 여러 단어들로 되어있지만, 제 1 공개키와 다르게 각 단어들은 중복이 가능하다.

암호문(암호화 된 문장)은 평문을 제 2 공개키를 만든 규칙의 반대로 재배치하여 만들어진다.

주어진 2개의 공개키와 암호문으로 평문을 복구하라.

입력

입력의 첫 줄에는 테스트 케이스의 수를 의미하는 하나의 정수가 입력된다. 정수는 100을 넘지 않는다.

각 테스트케이스마다 아래 항목들을 한 줄씩 입력받는다.

  • 한 문장의 단어 수 n (1 ≤ n ≤ 1 000)
  • 제 1 공개키
  • 제 2 공개키
  • 암호문

모든 단어들은 최소 1개, 최대 10개의 대문자들로 이루어져있다.

출력

각 케이스마다

  • 암호문을 해독한 평문

을 한 줄에 줄력한다.

예제 입력 1 복사

2
4
A B C D
D A B C
C B A P
3
SECURITY THROUGH OBSCURITY
OBSCURITY THROUGH SECURITY
TOMORROW ATTACK WE

예제 출력 1 복사

B A P C
WE ATTACK TOMORROW

 

문제풀이(1)

1. 1공개키의 위치에 맞는 2공개키의 인덱스 번호를 구한다.
    ㄴ 1공개키: A B C D, 2공개키: D A B C 일 때, 2공개키의 인덱스는 4 1 2 3 이다.


2. 암호문을 2공개키로 구한 인덱스번호에 맞춰서 해독한다.
    ㄴ 암호문: C B A P, 2공개키의 인덱스: 4 1 2 3 일 때, 해독하면 B A P C 가 된다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const T = Number(input.shift());

const answer = [];

const checkIndex = (publicKey1, publicKey2) => {
  return publicKey2.map((targetKey) => publicKey1.indexOf(targetKey));
};

for (let i = 0; i < T; i++) {
  const wordCount = Number(input.shift());
  const publicKey1 = input.shift().split(" ");
  const publicKey2 = input.shift().split(" ");
  const ciphertext = input.shift().split(" ");

  const matchIndex = checkIndex(publicKey1, publicKey2);

  const arr = Array.from({ length: wordCount }).fill("");

  matchIndex.forEach((el, idx) => {
    arr[el] = ciphertext[idx];
  });

  answer.push(arr.join(" "));
}

console.log(answer.join("\n"));

+ Recent posts