1. 알고리즘 문제

  1. 2729번 이진수 덧셈
// 이예고운
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void reverse(char* str) {
    int start = 0;
    int end = strlen(str) - 1;

    while (start < end) {
        char temp = str[start];
        str[start] = str[end];
        str[end] = temp;
        start++;
        end--;
    }
}

int main() {
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i++) {
        char binary[81], numbers[81];
        scanf("%s %s", binary, numbers);
        
        if (strlen(numbers) > strlen(binary)) { // 항상 binary가 더 긴 문자열이 되도록 설정
            char temp[81];
            strcpy(temp, binary);
            strcpy(binary, numbers);
            strcpy(numbers, temp);
        }

        reverse(binary);  // 문자열 뒤집기
        reverse(numbers);

        char ans[82];  // 결과를 저장할 배열
        int carry = 0;  // 캐리 초기화
        int t = 0;  // 결과 배열 인덱스

        // 두 문자열의 공통 길이 만큼 더하기
        for (int j = 0; j < strlen(numbers); j++) {
            int sum = (binary[j] - '0') + (numbers[j] - '0') + carry;  // 자리 수 합
            ans[t] = (sum % 2) + '0';  // 이진수 결과
            carry = sum / 2;  // 새로운 캐리 계산
            t++;
        }

        // 더 긴 문자열 binary의 나머지 자리 더하기
        for (int k = strlen(numbers); k < strlen(binary); k++) {
            int sum = (binary[k] - '0') + carry;
            ans[t] = (sum % 2) + '0';
            carry = sum / 2;
            t++;
        }

        // 최종 캐리 체크
        if (carry == 1) {
            ans[t] = '1';
            t++;
        }
        ans[t] = '\\0';

        reverse(ans);  // 결과 문자열 뒤집기

        // 앞의 0을 무시하고 출력
        int flag = 0;  // 처음 1이 나올 때까지 0 무시
        for (int v = 0; v < t; v++) {
            if (ans[v] == '1') flag = 1;  // 1이 나오면 출력 시작
            if (flag) printf("%c", ans[v]);
        }

        if (!flag) printf("0");
        printf("\\n");
    }

    return 0;
}

// 정재훈
#include <stdio.h>
#include <string.h>

char a[81], b[81];
int result[82];

int main(void)
{
    int n;
    scanf("%d", &n);
    for (int t = 0; t < n; t++)
    {
        int carry = 0;
        scanf("%s %s", a, b);
        int len_a = strlen(a);
        int len_b = strlen(b);
        int maxlen = len_a > len_b ? len_a : len_b;

        memset(result, 0, sizeof(result));

        int i = len_a - 1;
        int j = len_b - 1;
        int k = maxlen;

        while (i >= 0 || j >= 0 || carry)
        {
            int sum = carry;
            if (i >= 0)
                sum += a[i--] - '0';
            if (j >= 0)
                sum += b[j--] - '0';

            result[k--] = sum % 2;
            carry = sum / 2;
        }

        int start = 0;
        while (start <= maxlen && result[start] == 0)
        {
            start++;
        }

        if (start > maxlen)
        {
            printf("0");
        }
        else
        {
            for (int m = start; m <= maxlen; m++)
            {
                printf("%d", result[m]);
            }
        }
        printf("\\n");
    }

}

// 신서윤
#include<stdio.h>
#include<string.h>

void move(char a[], int max) {
   int a_len = strlen(a);
   for (int i = a_len - 1; i >= 0; i--) {
      a[i + max - a_len] = a[i];
   }
   for (int i = 0; i < max - a_len; i++) {
      a[i] = '0';
   }
   a[max] = '\\0';
}

int main() {
   int T;
   char A[81], B[81];
   int result[81];

   scanf("%d", &T);
   for (int i = 0; i < T; i++) {
      int carry = 0, A_len, B_len, max, a, b, temp, start = 1;
      scanf("%s %s", A, B);
      A_len = strlen(A);
      B_len = strlen(B);

      if (A_len >= B_len) {
         max = A_len;
         move(B, max);
      }
      else if (A_len < B_len) {
         max = B_len;
         move(A, max);
      }

      for (int j = max - 1; j >= 0; j--) {
         a = A[j] - '0';
         b = B[j] - '0';
         temp = a + b + carry;
         result[j] = temp % 2;
         carry = temp / 2;
      }
      if (carry == 1) {
         printf("%d", carry);
         start = 0;
      }
      for (int k = 0; k < max; k++) {
         if (start && result[k] == 0) {
            continue;
         }
         else {
            printf("%d", result[k]);
            start = 0;
         }
      }
      if (start) {
         printf("0");
      }

      printf("\\n");
   }
   return 0;
}

  1. 9461번 파도반 수열
// 이예고운
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    int n;
    scanf("%d", &n);

    long long dp[100] = { 1,1,1,2,2 };
    for (int i = 5; i < 100; i++) {
        dp[i] = dp[i - 1] + dp[i - 5];
    }

    for (int i = 0; i < n; i++) {
        int num;
        scanf("%d", &num);
        printf("%lld\\n", dp[num - 1]);
    }
    return 0;
}

// 정재훈
#include <stdio.h>

int main(void)
{
    int t;
    scanf("%d", &t);
    for (size_t j = 0; j < t; j++)
    {
        long long int dp[101];
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 1;
        dp[3] = 1;
        dp[4] = 2;
        dp[5] = 2;
        int n;
        scanf("%d", &n);
        for (size_t i = 6; i <= n; i++)
        {
            dp[i] = dp[i - 1] + dp[i - 5];
        }
        printf("%lld\\n", dp[n]);
    }
}
  1. 31926번 밤양갱
// 이예고운
#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);

    int ans = 10; // 처음 daldidalgo + daldidan 입력하는 데 10초 필요

    int temp = 1; // 초기 기준 temp = 1
    while (n >= temp * 2) { // temp가 두 배가 될 때마다 시간 1초 증가
        ans++;
        temp *= 2;
    }

    printf("%d\\n", ans);

    return 0;
}

// 신서윤

#include<stdio.h>

int main() {
   long long sum = 10;
   long long N;
   scanf("%lld", &N);
   if (N == 1) {
      printf("%lld", sum);
      return 0;
   }

   while (N != 1) {
      if (N % 2 == 0) {
         sum += 1;
         N /= 2;
      }
      else {
         sum += 1;
         N -= 1;
      }
   }
   printf("%lld", sum);

   return 0;
}
# 정재훈
import math
a = int(input())
print(int(math.log(a,2))+10)
  1. 4134번 다음 소수
// 이예고운
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long long next_prime(long long n) {
    if (n <= 2) return 2; 
    if (n % 2 == 0) n++;

    while (1) {
        int is_prime = 1; // 소수 여부를 판별하는 변수
        for (long long i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                is_prime = 0;
                break;
            }
        }
        if (is_prime == 1) {
            return n; // 소수라면 반환
        }
        n += 2; // 홀수 이동
    }
}

int main() {
    int n;
    scanf("%d", &n);

    long long num = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &num);
        long long result = next_prime(num);
        printf("%lld\\n", result);
    }

    return 0;
}
// 신서윤

#include<stdio.h>

int main() {
   long long m, n;
   scanf("%lld", &m);
   long long result;
   long long escape = 1;
   int temp;

   for (long long i = 0; i < m; i++) {
      scanf("%lld", &n);
      temp = n + 1;
      if (temp % 2 == 0) {
         temp += 1;
      }
      while(escape){
         for (long long k = 2; k <= temp/2; k++) {
            if (temp % k == 0) {
               break;
            }
            else if (k == temp / 2) {
               result = temp;
               escape = 0;
               break;
            }
         }
         if (escape) {
            temp += 2;
         }
      }
      escape = 1;
      printf("%lld\\n", result);
   }

   return 0;
}
// 정재훈
import sys
import math

def is_prime(num):
    if num <= 1:
        return False
    if num <= 3:
        return True
    if num % 2 == 0 or num % 3 == 0:
        return False
    i = 5
    while i * i <= num:
        if num % i == 0 or num % (i + 2) == 0:
            return False
        i += 6
    return True

def next_prime(n):
    while not is_prime(n):
        n += 1
    return n

T = int(input().strip())
results = []

for _ in range(T):
    n = int(input().strip())
    results.append(next_prime(n))

for result in results:
    print(result)

2. 알고리즘 공부 - Dynamic Programming

정의

동적 계획법(Dynamic Programming): 주어진 문제를 작은 하위 문제들로 나누고, 각 하위 문제의 결과를 메모이제이션하여, 동일한 하위 문제가 반복적으로 계산되는 것을 방지하는 최적화 기법

DP의 특징

  1. 최적 부분 구조: 큰 문제의 최적 해결책이 그 하위 문제들의 최적 해결책으로 구성되는 문제.
  2. 중복되는 하위 문제: 동일한 작은 문제들이 반복해서 계산되는 경우가 많은 문제.

DP는 크게 두 가지 방식으로 구현할 수 있습니다: