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

 

4134번: 다음 소수

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다.

www.acmicpc.net

문제

정수 n(0 ≤ n ≤ 4*109)가 주어졌을 때, n보다 크거나 같은 소수 중 가장 작은 소수 찾는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다.

출력

각각의 테스트 케이스에 대해서 n보다 크거나 같은 소수 중 가장 작은 소수를 한 줄에 하나씩 출력한다.

예제 입력 1 복사

3
6
20
100

예제 출력 1 복사

7
23
101

 

문제풀이(1)

주어진 수의 다음 소수를 구하는 문제이다.
소수는 1과 자기 자신만을 약수로 가지는 수이다. 1은 소수가 아니다.
소수 판별 함수를 구현한다음 주어진 수의 다음 수 부터 소수인지 판별하여 소수일 경우 출력하면 된다.

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

const answer = [];

const isPrime = (number) => {
  if (number < 2) return false;

  for (let i = 2; i <= Math.sqrt(number); i++) {
    if (number % i === 0) {
      return false;
    }
  }

  return true;
};

for (let i = 0; i < T; i++) {
  let number = arr[i];
  while (true) {
    if (isPrime(number)) {
      break;
    } else {
      number++;
    }
  }

  answer.push(number);
}

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

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

 

1969번: DNA

DNA란 어떤 유전물질을 구성하는 분자이다. 이 DNA는 서로 다른 4가지의 뉴클레오티드로 이루어져 있다(Adenine, Thymine, Guanine, Cytosine). 우리는 어떤 DNA의 물질을 표현할 때, 이 DNA를 이루는 뉴클레오

www.acmicpc.net

문제

DNA란 어떤 유전물질을 구성하는 분자이다. 이 DNA는 서로 다른 4가지의 뉴클레오티드로 이루어져 있다(Adenine, Thymine, Guanine, Cytosine). 우리는 어떤 DNA의 물질을 표현할 때, 이 DNA를 이루는 뉴클레오티드의 첫글자를 따서 표현한다. 만약에 Thymine-Adenine-Adenine-Cytosine-Thymine-Guanine-Cytosine-Cytosine-Guanine-Adenine-Thymine로 이루어진 DNA가 있다고 하면, “TAACTGCCGAT”로 표현할 수 있다. 그리고 Hamming Distance란 길이가 같은 두 DNA가 있을 때, 각 위치의 뉴클오티드 문자가 다른 것의 개수이다. 만약에 “AGCAT"와 ”GGAAT"는 첫 번째 글자와 세 번째 글자가 다르므로 Hamming Distance는 2이다.

우리가 할 일은 다음과 같다. N개의 길이 M인 DNA s1, s2, ..., sn가 주어져 있을 때 Hamming Distance의 합이 가장 작은 DNA s를 구하는 것이다. 즉, s와 s1의 Hamming Distance + s와 s2의 Hamming Distance + s와 s3의 Hamming Distance ... 의 합이 최소가 된다는 의미이다.

입력

첫 줄에 DNA의 수 N과 문자열의 길이 M이 주어진다. 그리고 둘째 줄부터 N+1번째 줄까지 N개의 DNA가 주어진다. N은 1,000보다 작거나 같은 자연수이고, M은 50보다 작거나 같은 자연수이다.

출력

첫째 줄에 Hamming Distance의 합이 가장 작은 DNA 를 출력하고, 둘째 줄에는 그 Hamming Distance의 합을 출력하시오. 그러한 DNA가 여러 개 있을 때에는 사전순으로 가장 앞서는 것을 출력한다.

예제 입력 1 복사

5 8
TATGATAC
TAAGCTAC
AAAGATCC
TGAGATAC
TAAGATGT

예제 출력 1 복사

TAAGATAC
7

예제 입력 2 복사

4 10
ACGTACGTAC
CCGTACGTAG
GCGTACGTAT
TCGTACGTAA

예제 출력 2 복사

ACGTACGTAA
6

 

문제풀이(1)

Hamming Distance의 합이 가장 작은 DNA는 각 자리수별 가장 많이 등장한 DNA며,
Hamming Distance의 합은 가장 작은 DNA를 나열한 것에서 각 자리수마다 다른 것을 더한 값이다.
1. 각 자리수별 가장 많이 등장한 DNA를 찾는다.
2. 각 자리수별 Hamming Distance의 합을 구한다.

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);

let hammingDistanceDNA = "";
let countHammingDistanceDNA = 0;

for (let i = 0; i < M; i++) {
  const map = new Map();
  for (let j = 0; j < N; j++) {
    const dna = input[j][i];
    map.has(dna) ? map.set(dna, map.get(dna) + 1) : map.set(dna, 1);
  }
  const hamming = [...map].sort().reduce((a, b) => (a[1] >= b[1] ? a : b));
  hammingDistanceDNA += hamming[0];
  countHammingDistanceDNA += N - hamming[1];
}

console.log(hammingDistanceDNA);
console.log(countHammingDistanceDNA);

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

 

28278번: 스택 2

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

www.acmicpc.net

문제

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

명령은 총 다섯 가지이다.

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

입력

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

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

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

출력

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

예제 입력 1 복사

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

예제 출력 1 복사

1
2
5
3
3
-1
-1

 

문제풀이(1)

1. 1 X: 정수 X를 스택에 넣는다. (1 ≤ X ≤ 100,000)
2. 2: 스택에 정수가 있다면 맨 위의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
3. 3: 스택에 들어있는 정수의 개수를 출력한다.
4. 4: 스택이 비어있으면 1, 아니면 0을 출력한다.
5. 5: 스택에 정수가 있다면 맨 위의 정수를 출력한다. 없다면 -1을 대신 출력한다.
위의 조건에 맞게 스택을 구현하면 된다.

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

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

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

  push(value) {
    const node = new Node(value);

    if (!this.head) {
      this.head = node;
    } else {
      node.prev = this.tail;
      this.tail.next = node;
    }

    this.tail = node;
    this.size++;
  }

  pop() {
    if (this.size === 0) {
      return -1;
    }

    const value = this.tail.value;

    if (this.head === this.tail) {
      this.head = null;
      this.tail = null;
    } else {
      this.tail = this.tail.prev;
      this.tail.next = null;
    }

    this.size--;

    return value;
  }

  getSize() {
    return this.size;
  }

  empty() {
    return this.size ? 0 : 1;
  }

  getTop() {
    return this.tail ? this.tail.value : -1;
  }
}

const stack = new Stack();

let answer = "";

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

  switch (command) {
    case "1":
      stack.push(value);
      break;
    case "2":
      answer += `${stack.pop()}\n`;
      break;
    case "3":
      answer += `${stack.getSize()}\n`;
      break;
    case "4":
      answer += `${stack.empty()}\n`;
      break;
    case "5":
      answer += `${stack.getTop()}\n`;
      break;
  }
}

console.log(answer.trim());

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

 

2491번: 수열

0에서부터 9까지의 숫자로 이루어진 N개의 숫자가 나열된 수열이 있다. 그 수열 안에서 연속해서 커지거나(같은 것 포함), 혹은 연속해서 작아지는(같은 것 포함) 수열 중 가장 길이가 긴 것을 찾

www.acmicpc.net

문제

0에서부터 9까지의 숫자로 이루어진 N개의 숫자가 나열된 수열이 있다. 그 수열 안에서 연속해서 커지거나(같은 것 포함), 혹은 연속해서 작아지는(같은 것 포함) 수열 중 가장 길이가 긴 것을 찾아내어 그 길이를 출력하는 프로그램을 작성하라. 

예를 들어 수열 1, 2, 2, 4, 4, 5, 7, 7, 2 의 경우에는 1 ≤ 2 ≤ 2 ≤ 4 ≤ 4 ≤ 5 ≤ 7 ≤ 7 이 가장 긴 구간이 되므로 그 길이 8을 출력한다. 수열 4, 1, 3, 3, 2, 2, 9, 2, 3 의 경우에는 3 ≥ 3 ≥ 2 ≥ 2 가 가장 긴 구간이 되므로 그 길이 4를 출력한다. 또 1, 5, 3, 6, 4, 7, 1, 3, 2, 9, 5 의 경우에는 연속해서 커지거나 작아지는 수열의 길이가 3 이상인 경우가 없으므로 2를 출력하여야 한다.

입력

첫째 줄에는 수열의 길이 N이 주어지고, 둘째 줄에는 N개의 숫자가 빈칸을 사이에 두고 주어진다. N은 1 이상 100,000 이하의 정수이다.

출력

첫째 줄에 가장 긴 길이를 출력한다.

예제 입력 1 복사

9
1 2 2 4 4 5 7 7 2

예제 출력 1 복사

8

예제 입력 2 복사

9
4 1 3 3 2 2 9 2 3

예제 출력 2 복사

4

 

문제풀이(1)

연속해서 커지거나 작아지는 수열이 가장 큰 길이를 구하면된다.
연속해서 커지는지 확인하는 로직, 연속해서 작아지는지 확인하는 로직 2개가 필요하다.
같은 숫자 예를들어 2 -> 2는 연속해서 작아지거나 커지는 것으로 간주한다.

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

const sequence = arr[0].split(" ").map(Number);

let upCount = 1;
let downCount = 1;

const answer = [];

for (let i = 0; i < Number(N); i++) {
  const nowNum = sequence[i];
  const nextNum = sequence[i + 1];

  if (nowNum <= nextNum) {
    upCount++;
  } else if (nowNum > nextNum) {
    upCount = 1;
  }

  if (nowNum >= nextNum) {
    downCount++;
  } else if (nowNum < nextNum) {
    downCount = 1;
  }
  answer.push(upCount);
  answer.push(downCount);
}

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

 

문제풀이(2)

1. 배열에 모든 count를 넣는 것이 아니라 바로 비교하여 메모리 최적화
2. 최고 값을 찾는 max 메서드를 사용하지 않음으로 실행시간 최적화
메모리 - 20132kb -> 12192kb
실행시간 - 208ms -> 188ms

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

const sequence = arr[0].split(" ").map(Number);

let upCount = 1;
let upResult = 1;

let downCount = 1;
let downResult = 1;

for (let i = 0; i < Number(N); i++) {
  const nowNum = sequence[i];
  const nextNum = sequence[i + 1];

  if (nowNum <= nextNum) {
    upCount++;
    if (upCount >= upResult) {
      upResult = upCount;
    }
  } else if (nowNum > nextNum) {
    upCount = 1;
  }

  if (nowNum >= nextNum) {
    downCount++;
    if (downCount >= downResult) {
      downResult = downCount;
    }
  } else if (nowNum < nextNum) {
    downCount = 1;
  }
}

console.log(upResult >= downResult ? upResult : downResult);

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

 

2331번: 반복수열

첫째 줄에 반복되는 부분을 제외했을 때, 수열에 남게 되는 수들의 개수를 출력한다.

www.acmicpc.net

문제

다음과 같이 정의된 수열이 있다.

  • D[1] = A
  • D[n] = D[n-1]의 각 자리의 숫자를 P번 곱한 수들의 합

예를 들어 A=57, P=2일 때, 수열 D는 [57, 74(=52+72=25+49), 65, 61, 37, 58, 89, 145, 42, 20, 4, 16, 37, …]이 된다. 그 뒤에는 앞서 나온 수들(57부터가 아니라 58부터)이 반복된다.

이와 같은 수열을 계속 구하다 보면 언젠가 이와 같은 반복수열이 된다. 이때, 반복되는 부분을 제외했을 때, 수열에 남게 되는 수들의 개수를 구하는 프로그램을 작성하시오. 위의 예에서는 [57, 74, 65, 61]의 네 개의 수가 남게 된다.

입력

첫째 줄에 A(1 ≤ A ≤ 9999), P(1 ≤ P ≤ 5)가 주어진다.

출력

첫째 줄에 반복되는 부분을 제외했을 때, 수열에 남게 되는 수들의 개수를 출력한다.

예제 입력 1 복사

57 2

예제 출력 1 복사

4

 

문제풀이(1)

주어진 수 A부터 한자리수씩 A^P로 계산하여 더한 값을 배열에 추가한 뒤 배열에 한번이라도 나왔던 수라면 반복을 정지한다.
[57, 74(=5^2+7^2=25+49), 65(=7^2+4^2=49+16), 61, 37, 58, 89, 145, 42, 20, 4, 16, 37]

그 후 한번이라도 나왔던 수가 몇번째 인덱스에 추가되었는지 확인하면 반복수열을 제거했을 때 남는 수열의 개수를 구할 수 있다.

57, 74, 65, 61, 37, 58, 89, 145, 42, 20, 4, 16, 37 일 경우 37이 두번등장 하기 때문에 그 사이는 반복수열이다.
반복수열을 제거하면 57, 74, 65, 61 이므로 4개가 남는데 이때, 37이 처음으로 나온 index값은 4이므로 4를 출력하면 반복수열을 제외한 나머지 수열의 개수를 알 수 있다.

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

const arr = [A];

const answer = [];

while (true) {
  const prevNum = String(arr.at(-1));
  const nextNum = prevNum.split("").reduce((acc, cur) => acc + Number(cur) ** P, 0);

  if (arr.includes(nextNum)) {
    console.log(arr.indexOf(nextNum));
    break;
  }

  arr.push(nextNum);
}

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

 

2776번: 암기왕

연종이는 엄청난 기억력을 가지고 있다. 그래서 하루 동안 본 정수들을 모두 기억 할 수 있다. 하지만 이를 믿을 수 없는 동규는 그의 기억력을 시험해 보기로 한다. 동규는 연종을 따라 다니며,

www.acmicpc.net

문제

연종이는 엄청난 기억력을 가지고 있다. 그래서 하루 동안 본 정수들을 모두 기억 할 수 있다. 하지만 이를 믿을 수 없는 동규는 그의 기억력을 시험해 보기로 한다. 동규는 연종을 따라 다니며, 연종이 하루 동안 본 정수들을 모두 ‘수첩1’에 적어 놓았다. 그것을 바탕으로 그가 진짜 암기왕인지 알아보기 위해, 동규는 연종에게 M개의 질문을 던졌다. 질문의 내용은 “X라는 정수를 오늘 본 적이 있는가?” 이다. 연종은 막힘없이 모두 대답을 했고, 동규는 연종이 봤다고 주장하는 수 들을 ‘수첩2’에 적어 두었다. 집에 돌아온 동규는 답이 맞는지 확인하려 하지만, 연종을 따라다니느라 너무 힘들어서 여러분에게 도움을 요청했다. 동규를 도와주기 위해 ‘수첩2’에 적혀있는 순서대로, 각각의 수에 대하여, ‘수첩1’에 있으면 1을, 없으면 0을 출력하는 프로그램을 작성해보자.

입력

첫째 줄에 테스트케이스의 개수 T가 들어온다. 다음 줄에는 ‘수첩 1’에 적어 놓은 정수의 개수 N(1 ≤ N ≤ 1,000,000)이 입력으로 들어온다. 그 다음 줄에  ‘수첩 1’에 적혀 있는 정수들이 N개 들어온다. 그 다음 줄에는 ‘수첩 2’에 적어 놓은 정수의 개수 M(1 ≤ M ≤ 1,000,000) 이 주어지고, 다음 줄에 ‘수첩 2’에 적어 놓은 정수들이 입력으로 M개 들어온다. 모든 정수들의 범위는 int 로 한다.

출력

‘수첩2’에 적혀있는 M개의 숫자 순서대로, ‘수첩1’에 있으면 1을, 없으면 0을 출력한다.

예제 입력 1 복사

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

예제 출력 1 복사

1
1
0
0
1

 

문제풀이(1)

기억하고 있는 수첩2에 있는 수들이 주어진 수첩2에 있는 수들중에 있다면 1, 없다면 0을 출력하는 문제이다.
수첩 1의 수들을 오름차순으로 정렬한다.
2진탐색으로 수첩2에 있는 수들을 하나씩 탐색하여 있다면 1, 없다면 0을 출력한다.

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 binarySearch = (arr, targetNum) => {
  let low = 0;
  let high = arr.length - 1;
  let result = 0;

  while (low <= high) {
    let mid = Math.floor((low + high) / 2);

    if (arr[mid] < targetNum) {
      low = mid + 1;
    } else if (arr[mid] > targetNum) {
      high = mid - 1;
    } else {
      result = 1;
      break;
    }
  }

  return result;
};

for (let i = 0; i < T; i++) {
  input.shift();
  const note1 = input
    .shift()
    .split(" ")
    .map(Number)
    .sort((a, b) => a - b);
  input.shift();
  const note2 = input.shift().split(" ").map(Number);

  note2.forEach((num) => {
    answer.push(binarySearch(note1, num));
  });
}

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

 

문제풀이(2)

Set을 사용한 풀이

이진 탐색을 사용했을 때보다 코드의 가독성은 올라갔지만 실행시간, 메모리 측면에서 좋지 않은 성적을 보여줬다.

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

for (let i = 0; i < T; i++) {
  input.shift();
  const note1 = input
    .shift()
    .split(" ")
    .map(Number)
    .sort((a, b) => a - b);
  const note1Set = new Set(note1);

  input.shift();
  const note2 = input.shift().split(" ").map(Number);

  note2.forEach((num) => {
    answer.push(note1Set.has(num) ? 1 : 0);
  });
}

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

+ Recent posts