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

 

20186번: 수 고르기

첫 번째 줄에 주어진 N개의 수 중 K개의 수를 고를 때, 전체점수의 최댓값을 출력한다.

www.acmicpc.net

문제

N개의 자연수가 좌우로 배열되어 있다. 여러분은 이 중 K개를 골라야 한다. 고를 때는 K개 모두를 한번에 골라야 한다.

여러분이 고른 수 각각에 대해서 그 수의 점수를 계산할 것이다. 점수는 자신의 수에서 자신의 왼쪽에 있는 수 중 선택된 수의 개수를 뺀 값이다. 이렇게 고른 수 각각에 그 점수를 계산한 후 전체점수는 계산된 점수들의 합이다. 여러분은 전체점수가 최대가 되도록 K개의 수를 골라야 한다.

예를 들어서, N = 5개의 자연수가 순서대로 2 3 1 2 1 로 주어지고, K = 3이라고 하자. 만약 첫 번째 2와 두 개의 1을 골랐다면, 각 수의 점수를 계산해서 나열하면 2 0 −1과 같다. 따라서 전체 점수는 1이다. 만약 첫 번째 2와 3, 그리고 두 번째 2를 고르고, 각 수의 점수를 계산해서 나열하면, 2 2 0과 같다. 따라서 전체점수는 4이다. 이 예에서 전체점수의 최댓값은 4이다.

N개의 자연수 배열과 양의 정수 K가 주어질 때, 전체점수의 최댓값을 출력하는 프로그램을 작성하시오.

입력

첫 번째 줄에 N과 K가 공백 하나를 사이로 두고 주어진다. 두 번째 줄에 N개의 자연수가 공백 하나를 사이에 두고 주어진다.

출력

첫 번째 줄에 주어진 N개의 수 중 K개의 수를 고를 때, 전체점수의 최댓값을 출력한다.

제한

  • 1 ≤ N ≤ 5 000
  • 1 ≤ K ≤ N
  • 주어지는 자연수는 1 이상 100 000 이하

서브태스크

번호배점제한
1 4 N ≤ 3
2 25 N ≤ 20
3 7 K = 1
4 9 K = 2
5 15 주어지는 N개의 수가 단조증가(감소하지 않는 순서)로 정렬되어 있다. 이는 즉, N개의 수 각각에 대해 그 수의 왼쪽에는 해당 수 이하의 값들만 있고, 오른쪽에는 해당 수 이상의 값들만 있다는 뜻이다.
6 40 추가 제약 조건 없음

예제 입력 1 복사

5 3
2 3 1 2 1

예제 출력 1 복사

4

예제 입력 2 복사

6 2
4 1 5 2 6 3

예제 출력 2 복사

10

 

문제풀이(1)

n개의 수 중 k개를 고를 때, 전체 점수의 최댓값을 구하는 문제이다.
최댓값을 구하는 문제이기때문에 내림차순으로 정렬한뒤 큰 수 k개를 찾으면 될 것이다.
마지막으로 가장 큰 K개의 숫자의 합에서 K개의 숫자를 이루는 연속된 자연수의 합을 뺀 값을 구하면된다.

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

const [n, k] = input.shift().split(" ").map(Number);
const arr = input[0]
  .split(" ")
  .map(Number)
  .sort((a, b) => b - a);

let answer = 0;

for (let i = 0; i < k; i++) {
  answer += arr[i];
}

// 가장 큰 K개의 숫자의 합에서 K개의 숫자를 이루는 연속된 자연수의 합을 뺀 값
console.log(answer - (k * (k - 1)) / 2);

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

 

9417번: 최대 GCD

첫째 줄에 테스트 케이스의 개수 N (1 < N < 100)이 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 양의 정수 M (1 < M < 100)개가 주어진다. 모든 수는 -231보다 크거나 같고, 231 -1보다 작거나

www.acmicpc.net

문제

정수 M개가 주어졌을 때, 모든 두 수의 쌍 중에서 가장 큰 최대공약수 찾는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 N (1 < N < 100)이 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 양의 정수 M (1 < M < 100)개가 주어진다. 모든 수는 -231보다 크거나 같고, 231 -1보다 작거나 같다. 

출력

각 테스트 케이스마다, 입력으로 주어진 수의 모든 두 수의 쌍의 최대공약수 중 가장 큰 값을 출력한다.

예제 입력 1 복사

3
10 20 30 40
7 5 12
125 15 25

예제 출력 1 복사

20
1
25

 

문제풀이(1)

유클리드 호제법을 사용해서 각 수들의 최대공약수를 구하면되는 문제이다.

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 result = [];

const getGCD = (num1, num2) => (num2 > 0 ? getGCD(num2, num1 % num2) : num1);

for (let i = 0; i < N; i++) {
  const numbers = input[i].split(" ").map(BigInt);
  let max = 0;
  for (let j = 0; j < numbers.length; j++) {
    for (let k = j + 1; k < numbers.length; k++) {
      let gcd = getGCD(numbers[j], numbers[k]);
      if (gcd > max) max = gcd;
    }
  }
  result.push(max.toString());
}

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

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

 

1337번: 올바른 배열

첫째 줄에 배열의 크기 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 배열의 원소가 한 줄에 하나씩 주어진다. 원소는 1,000,000,000보다 작거나 같은 음이 아닌 정수이

www.acmicpc.net

문제

올바른 배열이란 어떤 배열 속에 있는 원소 중 5개가 연속적인 것을 말한다. (연속적인 것이란 5개의 수를 정렬했을 때, 인접한 수의 차이가 1인 것을 말한다.)

예를 들어 배열 {6, 1, 9, 5, 7, 15, 8}은 올바른 배열이다. 왜냐하면 이 배열 속의 원소인 5, 6, 7, 8, 9가 연속이기 때문이다.

배열이 주어지면, 이 배열이 올바른 배열이 되게 하기 위해서 추가되어야 할 원소의 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 배열의 크기 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 배열의 원소가 한 줄에 하나씩 주어진다. 원소는 1,000,000,000보다 작거나 같은 음이 아닌 정수이다. 배열에 중복되는 수는 없다.

출력

첫째 줄에 입력으로 주어진 배열이 올바른 배열이 되게 하기 위해서 추가되어야할 원소의 최소 개수를 출력한다.

예제 입력 1 복사

3
5
6
7

예제 출력 1 복사

2

예제 입력 2 복사

6
5
7
9
8492
8493
192398

예제 출력 2 복사

2

 

문제풀이(1)

배열안에 5개 연속으로 나올 수 있는 경우 0, 없을 경우 추가해야할 원소의 최소 개수를 구하는 문제이다.
주어진 배열에 값들을 오름차순으로 정렬한다.
연속적으로 숫자를 추가한 뒤 필요하지 않은 값들을 제거하여 크기를 비교한다.

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

const getMaxContinuousNum = (numbers) => {
  let max = 0;

  for (let i = 0; i < numbers.length; i++) {
    const set = new Set([numbers[i] + 1, numbers[i] + 2, numbers[i] + 3, numbers[i] + 4]);
    let cnt = 0;

    for (let j = 0; j < numbers.length; j++) {
      if (set.has(numbers[j])) {
        cnt++;
      }
    }

    max = Math.max(max, cnt);
  }

  return max;
};

const [N, ...numbers] = input.map(Number);
numbers.sort((a, b) => a - b);

console.log(4 - getMaxContinuousNum(numbers));

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

 

13706번: 제곱근

첫째 줄에 양의 정수 N이 주어진다. 정수 N의 제곱근은 항상 정수이며, N의 길이는 800자리를 넘지 않는다.

www.acmicpc.net

문제

정수 N이 주어졌을 때, N의 제곱근을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 양의 정수 N이 주어진다. 정수 N의 제곱근은 항상 정수이며, N의 길이는 800자리를 넘지 않는다.

출력

첫째 줄에 정수 N의 제곱근을 출력한다.

예제 입력 1 복사

36

예제 출력 1 복사

6

예제 입력 2 복사

81

예제 출력 2 복사

9

 

문제풀이(1) - 실패

sqrt 메서드를 사용해서 풀면 될 줄 알았지만 되지 않았다.

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

console.log(Math.sqrt(number.toString()));

 

문제풀이(2)

알고리즘이 잘 생각나지 않아서 검색한 결과 이진탐색으로 풀 수 있다는 것을 알았다.

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

const binarySearch = (number) => {
  let low = 1n;
  let high = BigInt(number);

  while (low <= high) {
    let mid = (low + high) / 2n;

    if (mid ** 2n > number) {
      high = mid - 1n;
    } else if (mid ** 2n < number) {
      low = mid + 1n;
    } else {
      return mid;
    }
  }
};

console.log(binarySearch(number).toString());

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

 

28279번: 덱 2

첫째 줄에 명령의 수 N이 주어진다. (1 ≤ N ≤ 1,000,000) 둘째 줄부터 N개 줄에 명령이 하나씩 주어진다. 출력을 요구하는 명령은 하나 이상 주어진다.

www.acmicpc.net

문제

정수를 저장하는 덱을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다.

  1. 1 X: 정수 X를 덱의 앞에 넣는다. (1 ≤ X ≤ 100,000)
  2. 2 X: 정수 X를 덱의 뒤에 넣는다. (1 ≤ X ≤ 100,000)
  3. 3: 덱에 정수가 있다면 맨 앞의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  4. 4: 덱에 정수가 있다면 맨 뒤의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  5. 5: 덱에 들어있는 정수의 개수를 출력한다.
  6. 6: 덱이 비어있으면 1, 아니면 0을 출력한다.
  7. 7: 덱에 정수가 있다면 맨 앞의 정수를 출력한다. 없다면 -1을 대신 출력한다.
  8. 8: 덱에 정수가 있다면 맨 뒤의 정수를 출력한다. 없다면 -1을 대신 출력한다.

입력

첫째 줄에 명령의 수 N이 주어진다. (1 ≤ N ≤ 1,000,000)

둘째 줄부터 N개 줄에 명령이 하나씩 주어진다.

출력을 요구하는 명령은 하나 이상 주어진다.

출력

출력을 요구하는 명령이 주어질 때마다 명령의 결과를 한 줄에 하나씩 출력한다.

예제 입력 1 복사

11
6
1 3
1 8
7
8
3
2 5
1 2
5
4
4

예제 출력 1 복사

1
8
3
8
3
5
3

 

문제풀이(1)

위의 데크로직을 구현하면 되는 문제이다. 시간이 다소 소요됐다.

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

class Node {
  constructor(value) {
    this.value = value;
    this.prev = null;
    this.next = null;
  }
}

class Deque {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }

  unshift(value) {
    // 정수 X를 덱의 앞에 넣는다.
    const node = new Node(value);
    if (!this.head) {
      this.tail = node;
    } else {
      node.next = this.head;
      this.head.prev = node;
    }
    this.head = node;
    this.size++;
  }

  push(value) {
    // 정수 X를 덱의 뒤에 넣는다.
    const node = new Node(value);
    if (!this.tail) {
      this.head = node;
    } else {
      node.prev = this.tail;
      this.tail.next = node;
    }
    this.tail = node;
    this.size++;
  }

  shift() {
    // 맨 앞의 정수를 빼고 출력한다.
    if (!this.head) {
      return -1;
    }
    const value = this.head.value;
    this.head = this.head.next;
    if (this.head) {
      this.head.prev = null;
    } else {
      this.tail = null;
    }
    this.size--;
    return value;
  }

  pop() {
    // 맨 뒤의 정수를 빼고 출력한다.
    if (!this.tail) {
      return -1;
    }
    const value = this.tail.value;
    this.tail = this.tail.prev;
    if (this.tail) {
      this.tail.next = null;
    } else {
      this.head = null;
    }
    this.size--;
    return value;
  }

  length() {
    // 덱에 들어있는 정수의 개수를 출력한다.
    return this.size;
  }

  isEmpty() {
    // 덱이 비어있으면 1, 아니면 0을 출력한다.
    return this.size === 0 ? 1 : 0;
  }

  getFront() {
    // 덱에 정수가 있다면 맨 앞의 정수를 출력한다.
    return this.head ? this.head.value : -1;
  }

  getBack() {
    // 덱에 정수가 있다면 맨 뒤의 정수를 출력한다.
    return this.tail ? this.tail.value : -1;
  }
}

const deque = new Deque();

let answer = "";

for (let i = 0; i < N; i++) {
  const [command, value] = input[i].split(" ").map(Number);

  // unshift, push, shift, pop, length, isEmpty, getFront, getBack
  switch (command) {
    case 1:
      deque.unshift(value);
      break;
    case 2:
      deque.push(value);
      break;
    case 3:
      answer += `${deque.shift()}\n`;
      break;
    case 4:
      answer += `${deque.pop()}\n`;
      break;
    case 5:
      answer += `${deque.length()}\n`;
      break;
    case 6:
      answer += `${deque.isEmpty()}\n`;
      break;
    case 7:
      answer += `${deque.getFront()}\n`;
      break;
    case 8:
      answer += `${deque.getBack()}\n`;
      break;
    default:
      break;
  }
}

console.log(answer.trim());

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

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

문제

자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열

입력

첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)

출력

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.

수열은 사전 순으로 증가하는 순서로 출력해야 한다.

예제 입력 1 복사

3 1

예제 출력 1 복사

1
2
3

예제 입력 2 복사

4 2

예제 출력 2 복사

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

 

문제풀이(1)

자신과 같거나 방문했던 노드는 선택하지 않는 점에서 DFS로 풀어야 한다고 생각했다.
찾아보니 이와 같은 문제를 백트래킹 문제라고 한다.

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

let result = "";
const answer = [];
const visited = new Array(N).fill(false);

const dfs = (count) => {
  if (count === M) {
    return (result += `${answer.join(" ")}\n`);
  }

  for (let i = 0; i < N; i++) {
    if (!visited[i]) {
      visited[i] = true;
      answer.push(i + 1);
      dfs(count + 1);
      answer.pop();
      visited[i] = false;
    }
  }
};

dfs(0);

console.log(result.trim());

+ Recent posts