기본 수학 1


1712번 (손익분기점)

const fs = require("fs");
const input = fs.readFileSync("./input.txt").toString().trim().split(' ');
const fixedCost = parseInt(input[0]);
const flexibleCost = parseInt(input[1]);
const productPrice = parseInt(input[2]);
const BEP = fixedCost / (productPrice - flexibleCost);
let answer = 0;
answer = Math.floor(BEP+1);
if ((productPrice - flexibleCost) <= 0) {
answer = -1;
}
console.log(answer);
  • fixedCost + (flexibleCost * BEP) = productPrice * BEP 가 될때가 손해도 이익도 없는 분기점이다.
  • 이를 정리하면 BEP = fixedCost / (productPrice - flexibleCost)가 된다.
  • 이는 손해도 이익도 없는 지점이므로 여기에 1개를 더 팔아야 이익이 시작된다. 따라서 답은 여기에 1을 더하고 소수점을 탈락시켜준다.
  • 그러나 손익분기점이 없는 경우 -1로 나타내어야 한다.
  • productPrice - flexibleCost가 음수이거나 0이면 이익이 나지 않아 손익분기점이 없으므로 이 경우는 -1을 출력하도록 한다.
  • 2292번 (벌집)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim();
    const inputNum = parseInt(input);
    let x = 0;
    let count = 1;
    let floorMax = 0;
    while (inputNum > floorMax) {
    x+=count;
    count++;
    floorMax = 6*x+1
    }
    if (inputNum == 1) {
    count = 1;
    }
    console.log(count);
  • 1은 1층, 1에서 2개의 방을 지나가면 2층, 1에서 3개의 방을 지나가면 3층이라고 생각했다.
  • 이렇게 되면 2층에서 가장 큰 숫자는 7, 3층에서 가장 큰 숫자는 19, 4층에서 가장 큰 숫자는 37이다.
  • 층에서 가장 큰 숫자는 6x+1이고 x = 1, 3, 6, 10… 으로 증가한다는 것을 알 수 있다.
  • 이는 한 층의 숫자 개수가 6, 12, 18로 6의 배수로 증가하기 때문이다.
  • 층에서 가장 큰 숫자를 floorMax라는 변수로 선언하고 위 규칙에 따라 x를 증가시키며 이를 inputNum이 floorMax보다 클 동안 반복하였다.
  • floorMax가 inputNum보다 커지면 inputNum은 그 층에 속하는 것으로 반복문을 종료한다.
  • count는 x의 증가를 도와주는 변수이지만 층의 수와 같기때문에 정답으로 count를 출력한다.
  • 그러나 inputNum이 1인 경우에는 정답은 1이므로 이 경우를 if문으로 예외처리 해주었다.
  • 1193번 (분수찾기)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim();
    const inputNum = parseInt(input);
    let count = 2;
    let topNumMax = 3;
    let topNum = 1;
    let bottomNumMax = 2;
    let bottomNum = 1;
    let answer = '';
    let isIncreasing = true;
    while (count < inputNum) {
    if (isIncreasing) {
    topNum++;
    } else {
    topNum--;
    }
    if (topNum == topNumMax) {
    isIncreasing = false;
    topNumMax += 2;
    }
    if (topNum == 1) {
    count++;
    isIncreasing = true;
    }
    count++;
    }
    count = 1;
    isIncreasing = true;
    while (count < inputNum) {
    if (isIncreasing) {
    bottomNum++;
    } else {
    bottomNum--;
    }
    if (bottomNum == bottomNumMax) {
    isIncreasing = false;
    bottomNumMax += 2;
    }
    if (bottomNum == 1) {
    count++;
    isIncreasing = true;
    }
    count++;
    }
    answer = topNum+'/'+bottomNum
    console.log(answer);
  • 분수의 분자를 topNum, 분모를 bottomNum으로 선언했다.
  • topNum과 bottomNum의 규칙을 찾았다.
  • 1에서는 1을 한번 더 반복하고 최고점을 찍고 다시 내려오는 것을 볼 수 있다.
  • isIncreasing이라는 boolean을 선언해서 정점에 도달하면 이를 false로 만들어 이때는 감소하도록 하였다.
  • 정점에 도달하면 정점(topNumMax, bottomNumMax)에 2가 더해진다.
  • 2869번 (달팽이는 올라가고 싶다)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim().split(' ');
    const upInDay = parseInt(input[0]);
    const downInNight = parseInt(input[1]);
    const UpInOneDay = upInDay - downInNight;
    const totalHeight = parseInt(input[2]);
    let answer = 0;
    answer = Math.ceil((totalHeight - upInDay) / UpInOneDay);
    answer++;
    console.log(answer);
  • 문제의 A를 upInDay, B를 downInNight, V를 totalHeight로 선언하여 값을 받았다.
  • 변수 UpInOneDay는 달팽이가 낮에 올라간 거리에서 밤에 떨어진 거리를 뺀 거리이다.
  • 달팽이는 정상에 올라가면 떨어지지 않으므로 totalHeight에서 upInDay를 뺀 값만큼 올라가게 되면 바로 다음날 정상에 올라갈 수 있다.
  • 위 값을 UpInOneDay로 나누고 소수점을 올림하면(예를 들어 2.5일 만에 도착한다고 하면 그날 하루가 지나면 3일이기 때문) 며칠만에 위 값에 도달하는지 알 수 있다.
  • 여기에서 다음 날 도착하기 때문에 1을 증가시켜준다.
  • 10250번 (ACM 호텔)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim().split('\n');
    const inputNum = input[0];
    let floor = 0;
    let distance = 0;
    let eachCase = '';
    let answer = '';
    for (let i = 1; i <= inputNum; i++) {
    eachCase = input[i].trim().split(' ');
    floor = eachCase[2] % eachCase[0];
    if (floor == 0) {
    floor = eachCase[0];
    }
    distance = Math.ceil(eachCase[2] / eachCase[0]);
    if (distance < 10) {
    String(distance);
    distance = '0' + distance;
    }
    answer = String(floor)+String(distance);
    console.log(parseInt(answer));
    }
  • for문으로 입력 첫째줄에 주어진 숫자만큼
  • 각각의 case를 eachCase에 배열로 담았다.
  • floor는 YYXX라는 방 호수 이름에서 YY에 해당한다.
  • floor는 몇번째 손님인지의 숫자를 층수로 나눈 나머지로 하여 구하고 만약 0일 경우 꼭대기층에 해당하므로 이 경우만 if문으로 예외처리 해주었다.
  • distance는 YYXX라는 방 호수 이름에서 XX에 해당한다.
  • distance는 몇번째 손님인지의 숫자를 층수로 나눈 몫에 소수점을 올림처리 해주었다.
  • 10보다 작을 경우 01, 02 이런식으로 출력되어야 하므로 이 경우도 예외처리 해주었다.
  • floor와 distance를 YYXX형태로 출력했다.
  • 2775번 (부녀회장이 될테야)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim().split('\n').map(Number);
    let answerArr = [];
    let maxN = 0;
    for (let i = 2; i <= 2 + input[0]; i+=2) { // 가장 큰 N의 크기 찾기
    if (input[i] > maxN) {
    maxN = input[i];
    }
    }
    let zeroFloor = []; // 0층 숫자 세팅
    for (let i = 1; i <= maxN; i++) {
    zeroFloor.push(i);
    }
    answerArr.push(zeroFloor);
    let maxK = 0;
    for (let i = 1; i <= 1 + input[0]; i+=2) { // 가장 큰 K의 크기 찾기
    if (input[i] > maxK) {
    maxK = input[i]
    }
    }
    let newFloor = [];
    for (let j = 1; j <= maxK; j++) { // 0으로 채워넣어 이중배열 완성
    newFloor = [];
    for (let i = 0; i < maxN; i++) {
    newFloor.push(0);
    }
    answerArr.push(newFloor);
    }
    let prevFloor = [];
    let humanNum = 0;
    for (let i = 1; i <= maxK; i++) { // 이중배열 안 0들을 알맞은 숫자로 바꾸기
    prevFloor = [];
    for (let j = 0; j < maxN; j++) {
    prevFloor.push(answerArr[i-1][j]);
    humanNum = prevFloor.reduce((acc, cur) => acc + cur, 0);
    answerArr[i][j] = humanNum;
    }
    }
    for (let i = 1; i < input.length; i+=2) {
    console.log(answerArr[input[i]][(input[i+1])-1]); // 입력에 따라 출력
    }
  • 입력 중 가장 큰 N과 K를 찾아 이에 따라 이중 배열을 만든다.
  • maxK = 2, maxN = 3 인 경우,
  • 0층은 항상 1,2,3… 이므로 for문을 이용하여 0층을 세팅한다.
  • 이후 prevFloor에 이전 층의 숫자를 하나씩 삽입하면서 reduce함수를 이용하여 prevFloor의 값의 합을 humanNum에 저장하고, 이를 answerArr의 해당 위치에 세팅한다.
  • 입력에 따라 출력한다.
  • 2839번 (설탕 배달)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim();
    const inputNum = parseInt(input);
    let answerArr = [];
    for (let i = 0; i <= inputNum; i++) {
    answerArr.push(-1);
    }
    let mem = 5000;
    for (let i = 3; i <= inputNum; i++) {
    mem = 5000;
    for (let j = 0; j <= i/5; j++) {
    for (let k = 0; k <= i/3; k++) {
    if (i == (5*j + 3*k) && mem > j+k) {
    mem = j+k;
    answerArr[i] = mem;
    }
    }
    }
    }
    console.log(answerArr[inputNum]);
  • answerArr를 만들어 해당 배열에 inputNum만큼의 -1을 push 하였다.
  • 3중 for문의 i는 상근이가 배달해야 할 설탕의 무게, j는 5kg 봉지의 개수, k는 3kg 봉지의 개수이다.
  • i가 5*j + 3*k와 같으면 정확하게 ikg 배달이 가능하다.
  • 이때 j+k개가 봉지의 개수이므로 변수 mem에 j+k를 넣고 배열을 업데이트 한다.
  • 만약 또 다시 i가 5*j + 3*k와 같으면 mem과 j+k를 비교하여 더 작은 것이 남는다.
  • 이렇게 정답이 입력된 배열이 완성되고 inputNum 인덱스의 값을 출력한다.
  • 10757번 (큰 수 A+B)

    const fs = require("fs");
    const input = fs.readFileSync("./input.txt").toString().trim().split(' ');
    const A = BigInt(input[0]);
    const B = BigInt(input[1]);
    let answer = A + B;
    console.log(answer.toString());
  • 만약 부전공을 하면서 C언어나 C++을 접하지 않았다면 이 문제에 대해 전혀 이해하지 못했을 것 같다.
  • BigInt는 2^53-1 보다 큰 정수를 표현할 수 있는 내장 객체이다.
  • BigInt는 toString()을 쓰지 않고 출력하면 숫자 맨 끝에 n이 딸려나오므로 toString()을 붙여서 출력한다.