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

 

2417번: 정수 제곱근

정수가 주어지면, 그 수의 정수 제곱근을 구하는 프로그램을 작성하시오.

www.acmicpc.net

문제

정수가 주어지면, 그 수의 정수 제곱근을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수 n이 주어진다. (0 ≤ n < 2^63)

출력

첫째 줄에 q2 ≥ n인 가장 작은 음이 아닌 정수 q를 출력한다.

예제 입력 1 복사

122333444455555

예제 출력 1 복사

11060446

 

문제풀이(1)

처음엔 간단하게 Math.sqrt를 사용해서 제곱근을 구하면 될 것이라 생각해서 풀어보았다.

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

// 제곱근을 찾는다.
let result = Math.floor(Math.sqrt(n));

// 제곱근보다 작을 경우 +1을 해준다.
console.log(result ** 2 < n ? result + 1 : result);

 

문제풀이(2)

이진 탐색으로 푸는 방법이 있다고하여 구현해보았다.

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

const binarySearch = (num) => {
  let low = 0;
  let high = num;
  while (low <= high) {
    let mid = Math.floor((low + high) / 2);
    if (mid * mid < num) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }

  return low;
};

console.log(binarySearch(n));

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

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

문제

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

  1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
  2. X가 2로 나누어 떨어지면, 2로 나눈다.
  3. 1을 뺀다.

정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

입력

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

출력

첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

예제 입력 1 복사

2

예제 출력 1 복사

1

예제 입력 2 복사

10

예제 출력 2 복사

3

 

문제풀이(1)

1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
2. X가 2로 나누어 떨어지면, 2로 나눈다.
3. 1을 뺀다.
위의 공식을 실행하면 된다. 횟수를 카운트해서 출력한다.
하지만, 10^6승의 수가 나왔을 경우 연산횟수가 많아 질 수 있기 때문에 dp로 이전 값을 가져와서 계산하는 방법을 사용했다.

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

const dp = new Array(num + 1).fill(0);

for (let i = 2; i <= num; i++) {
  dp[i] = dp[i - 1] + 1;

  if (i % 2 === 0) {
    dp[i] = Math.min(dp[i], dp[i / 2] + 1);
  }

  if (i % 3 === 0) {
    dp[i] = Math.min(dp[i], dp[i / 3] + 1);
  }
}

console.log(dp[num]);

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

 

1246번: 온라인 판매

첫째 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 입력된다. 둘째 줄부터 M+1번째 줄까지 i+1번째 줄에는 Pi(1 ≤ Pi ≤ 1,000,000)가 입력된다.

www.acmicpc.net

문제

경래는 닭을 기르는데 올 겨울 달걀 풍년으로 함박 웃음을 짓고 있다. 그리고 이 달걀을 영양란으로 둔갑하여 옥션에 판매하려한다.

경래는 총 N개의 달걀이 있고, 그의 잠재적인 고객은 총 M명이다. 그리고 각각의 i번째 고객은 각자 달걀 하나를 Pi 가격 이하로 살 수 있다고 밝혔다.

경래는 영양란이라 속인 죄책감에 한 고객에게 두 개 이상의 달걀은 팔지 않기로 하였다. 하지만 위의 규칙 하에 수익은 최대로 올리고 싶기에 얼마로 팔지 고민하고 있다. 즉, A가격에 달걀을 판다고 하면 Pi가 A가격보다 크거나 같은 모든 고객은 달걀을 산다는 뜻이다. (물론 달걀 총 수량을 초과하여 팔 수 는 없다)

문제는 이러한 경래를 도와 최대 수익을 올릴 수 있는 달걀의 가장 낮은 가격을 책정하는 것이다.

입력

첫째 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 입력된다. 둘째 줄부터 M+1번째 줄까지 i+1번째 줄에는 Pi(1 ≤ Pi ≤ 1,000,000)가 입력된다.

출력

첫째 줄에 경래가 책정한 가격과 이 가격으로 올릴 수 있는 수익을 출력한다.

예제 입력 1 복사

5 4
2
8
10
7

예제 출력 1 복사

7 21

 

문제풀이(1)

내림차순으로 정렬해서 최대수익과 달걀가격을 구하면 된다. 이때, 최대수익은 i + 1 * arr[i]이고, 달걀의 가격은 arr[i]이다.

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(Number);
arr.sort((a, b) => b - a);

const answer = [];

for (let i = 0; i < arr.length; i++) {
  if (i + 1 > N) {
    break;
  }

  // total - 최대 수익, value - 달걀 가격
  answer.push({ total: (i + 1) * arr[i], value: arr[i] });
}

answer.sort((a, b) => b.total - a.total);

console.log(answer[0].value, answer[0].total);

 

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

 

14469번: 소가 길을 건너간 이유 3

이웃 농장의 소가 길을 마구잡이로 건너는 것에 진절머리가 난 존은 극단의 결정을 내린다. 농장 둘레에 매우 큰 울타리를 짓는 것이다. 이렇게 하면 근처 농장 출신의 소가 들어올 일이 거의 없

www.acmicpc.net

문제

이웃 농장의 소가 길을 마구잡이로 건너는 것에 진절머리가 난 존은 극단의 결정을 내린다. 농장 둘레에 매우 큰 울타리를 짓는 것이다. 이렇게 하면 근처 농장 출신의 소가 들어올 일이 거의 없다. 이 일로 주변 소들이 분개하였다. 친구네 집에 놀러 갈 수 없을 뿐만 아니라, 매년 참가하던 국제 젖 짜기 올림피아드에도 올해는 참가할 수 없게 되었기 때문이다.

이웃 농장의 소 중 존의 농장에 방문할 수 있는 소가 조금 있긴 하지만, 그들도 안심할 수 있는 건 아니다. 존의 농장에 들어가는 문은 하나밖에 없고, 그 문을 통과하려면 감시관의 길고 긴 검문을 받아야 한다. 여러 마리의 소가 한 번에 들어가려고 하면 줄이 그 만큼 길어진다.

N마리의 소가 이 농장에 방문하러 왔다. 소가 도착한 시간과 검문받는 데 걸리는 시간은 소마다 다르다. (물론 같을 수도 있다.) 두 소가 동시에 검문을 받을 수는 없다. 예를 들어, 한 소가 5초에 도착했고 7초 동안 검문을 받으면, 8초에 도착한 그 다음 소는 12초까지 줄을 서야 검문을 받을 수 있다.

모든 소가 농장에 입장하려면 얼마나 걸리는 지 구해보자.

입력

첫 줄에 100 이하의 양의 정수 N이 주어진다. 다음 N줄에는 한 줄에 하나씩 소의 도착 시각과 검문 시간이 주어진다. 각각 1,000,000 이하의 양의 정수이다.

출력

모든 소가 농장에 입장하는 데 걸리는 최소 시간을 출력한다.

예제 입력 1 복사

3
2 1
8 3
5 7

예제 출력 1 복사

15

 

문제풀이(1)

1 2(1번소) 3(1번소 검사완료) 4 5(3번소) 6 7 8 9 10 11 12(3번소 검사완료) 13(2번소) 14 15(2번소 검사완료)
위와 같이 진행될 때 소는 먼저온 순서로 들어가는 형식이다. 그렇기때문에 소의 도착시간 순서로 정렬한 뒤 계산한다.
배열 순회할 때 마다 time에 start + end를 더해준다.
이때, 현재 time > start이면 time에 end 만 더해주고, time <= start 일 경우 start - time + end로 계산한다.
start - time을 하는 이유는 이전에 지나간 시간은 start에서 제거를 해야하기 때문이다.

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

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

let time = 0;

arr.forEach((value) => {
  const [start, end] = value;
  if (time > start) {
    time += end;
  } else {
    time += start - time + end;
  }
});

console.log(time);

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

 

14495번: 피보나치 비스무리한 수열

피보나치 비스무리한 수열은 f(n) = f(n-1) + f(n-3)인 수열이다. f(1) = f(2) = f(3) = 1이며 피보나치 비스무리한 수열을 나열하면 다음과 같다. 1, 1, 1, 2, 3, 4, 6, 9, 13, 19, ... 자연수 n을 입력받아 n번째 피보

www.acmicpc.net

문제

피보나치 비스무리한 수열은 f(n) = f(n-1) + f(n-3)인 수열이다. f(1) = f(2) = f(3) = 1이며 피보나치 비스무리한 수열을 나열하면 다음과 같다.

1, 1, 1, 2, 3, 4, 6, 9, 13, 19, ...

자연수 n을 입력받아 n번째 피보나치 비스무리한 수열을 구해보자!

입력

자연수 n(1 ≤ n ≤ 116)이 주어진다.

출력

n번째 피보나치 비스무리한 수를 출력한다.

예제 입력 1 복사

10

예제 출력 1 복사

19

 

문제풀이(1)

15624번 피보나치 수 7과 같은 DP 문제이다. 조건은 조금 다르다.
f(n) = f(n-1) + f(n-3) 해당 조건에 맞게 로직을 구현하면 된다.
f(1) = f(2) = f(3) = 1
또한, Int 범위를 벗어나는 경우가 있기 때문에 Bigint를 사용해야한다.

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

const dp = [BigInt(1), BigInt(1), BigInt(1)];

for (let i = 3; i < N; i++) {
  dp.push(dp[i - 1] + dp[i - 3]);
}

console.log(dp.at(-1).toString());

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

 

15624번: 피보나치 수 7

첫째 줄에 n번째 피보나치 수를 1,000,000,007으로 나눈 나머지를 출력한다.

www.acmicpc.net

문제

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다.

이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가 된다.

n=17일때 까지 피보나치 수를 써보면 다음과 같다.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597

n이 주어졌을 때, n번째 피보나치 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 n이 주어진다. n은 1,000,000보다 작거나 같은 자연수 또는 0이다.

출력

첫째 줄에 n번째 피보나치 수를 1,000,000,007으로 나눈 나머지를 출력한다.

예제 입력 1 복사

10

예제 출력 1 복사

55

예제 입력 2 복사

1000

예제 출력 2 복사

517691607

 

문제풀이(1)

이전에 풀었던 1755번 숫자 놀이와 같은 DP 문제이다.

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

const dp = [0, 1];

for (let i = 2; i <= num; i++) {
  dp.push((dp[i - 2] + dp[i - 1]) % 1000000007);
}

if (num === 0 || num === 1) {
  console.log(dp[num]);
} else {
  console.log(dp.at(-1));
}

+ Recent posts