Math

수학과 관련된 알고리즘 문제를 풀어볼 것이다.

나머지연산

문제 중 나머지를 구하라는 문제가 있으면 답을 다 구한후에 구하면 범위를 초과할 수 있기때문에 중간에 해줘야한다.

(A+B)%C = ((A%C)+(B%C))%C

ex) A = q1*c + r1, B = q2*c + r2
A+B = (q1+q2)*c + (r1+r2)
(A+B)%c = (r1+r2)%c
A%c = r1, B%c = r2
  • 곱하기의 경우에도 성립한다.

  • 하지만 나누기의 경우에는 성립하지않는다.(Modular Inverse를 구해야한다.)

  • 뺄셈의 경우 먼저 mod를 한 결과가 음수가 나올 수 있기때문에 (A-B)%M = ((A%M)-(B%M)+M)%M을 해줘야한다.

#include <iostream>
using namespace std;

int main(){
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
	// 첫째 줄에 (A+B)%C, 둘째 줄에 (A%C + B%C)%C, 셋째 줄에 (A×B)%C, 넷째 줄에 (A%C × B%C)%C를 출력한다.
    printf("%d\n%d\n%d\n%d",(a+b)%c,(a%c+b%c)%c,(a*b)%c,(a%c*b%c)%c);
}

최대공약수(Gretest Common Divisor)

두 수 A와 B의 최대공약수 G는 A와 B의 공통된 약수 중에서 가장 큰 정수이다. 이때 최대공약수가 1인 두 수를 서로소(Coprime)이라고 한다.

  1. 2부터 min(A,B)까지 모든 정수로 나누어보는 방법

  2. 유클리드 알고리즘(a를 b로 나눈 나머지를 r이라 했을 때, GCD(a,b)=GCD(b,r), r=0이면 그 때 b가 최대공약수이다.)

a<b인 경우엔느 a%b=a이므로 자동으로 a와 b가 바뀌게 된다. 그러므로 따로 대소관계를 비교해줄 필요가 없다.

  • 세 개이상의 최대공약수는 **GCD(a,b,c)=GCD(GCD(a,b),c)**와 같은 식으로 계속해서 구할 수 있다.

최소공배수(Least Common Multiple)

두 수의 공통된 배수 중에서 가장 작은 정수이다. 최소공배수는 최대공약수를 이용해서 구할 수 있다. 이 때, 최소공배수는 두 수보다 큰 수이므로 범위를 잘 확인해서 구해야한다.

  • **최대공약수 * 최소공배수 = A*B**이다.

  • 즉, **최소공배수 = (A*B)/최대공약수**이다.

진법 변환

10진법 수 N을 B진법으로 바꾸려면 N이 0이 될때까지 나머지를 계속해서 구하면된다.

10 to N

  • 10진법 수 N이 주어진다. 이 수를 B진법으로 바꿔 출력하는 프로그램을 작성하시오.

  • A: 10, B: 11, ..., F: 16, ..., Y: 34, Z: 35

B to 10

  • B진법 수 N이 주어진다. 이 수를 10진법으로 바꿔 출력하는 프로그램을 작성하시오.

  • A: 10, B: 11, ..., F: 16, ..., Y: 34, Z: 35

2 to 8

  • 2진수가 주어졌을 때, 8진수로 변환하는 프로그램을 작성하시오.

8 to 2

  • 8진수가 주어졌을 때, 2진수로 변환하는 프로그램을 작성하시오.

8 to -2

  • -2진법은 부호 없는 2진수로 표현이 된다. 2진법에서는 20, 21, 22, 23이 표현 되지만 -2진법에서는 (-2)0 = 1, (-2)1 = -2, (-2)2 = 4, (-2)3 = -8을 표현한다. 10진수로 1부터 표현하자면 1, 110, 111, 100, 101, 11010, 11011, 11000, 11001 등이다.

  • 나머지가 음수가 나오면 안된다.

  • 양수/-2

    • 2로 나누어 떨어지는 경우

  • 음수/-2

    • 2로 나누어 떨어지는 경우

A to B

  • A진법을 B진법으로 바꾸기

  • A진법 -> 10진법 -> B진법

소수

약수가 1과 자기 자신 밖에 없는 수이다.

N이 소수가 되려면, 2이상 N-1이하의 자연수로 나누어 떨어지면 안된다.

구현 방법

방법1

  • 시간복잡도 : O(n)

방법2

N의 약수 중에서 가장 큰 것은 N/2보다 작거나 같기 때문에 2이상 N/2이하의 자연수로 나누어 떨어지면된다.

  • 시간복잡도 : O(n)

방법3

N이 소수가 아니라면, N=a*b 로 나타낼 수 있다.(a<=b)

두 수 a와 b의 차이가 가장 작은 경우는 루트(n) 이다. 그러므로 2이상 루트(n)이하 의 자연수로 나누어 떨어지지 않는 수를 비교해보면된다.

예를 들어, N=24이다.

  • N=24의 약수 : 1 2 3 4 6 8 12 24

  • 1과 자기자신(24)제외한 약수 : 2 3 4 6 8 12

  • 루트(24) 는 약 4.xxxx이다. 루트(24)를 기준으로 반으로 나눌 수 있다.

  • 2 3 4 | 6 8 12

  • 루트(24)를 기준으로 작은수에서 나누어 떨어지는 수가 있다면 큰 쪽에서도 나누어 떨어지는 수가 있는 것이다. 그러므로 기준에서 작은수를 비교해 나누어 떨어지지 않는 수를 찾으면 된다.

  • 시간복잡도 : O(root(n))

주어진 수 N개 중에서 소수가 몇 개인지 찾아서 출력하는 프로그램을 작성하시오.

에라토스테네스의 체

1부터 N까지 범위 안에 들어가는 모든 소수를 구하려면 에라토스테네스의 체를 사용한다. 왜냐하면 각각의 수에 대해서 소수인지 아닌지 검사하는데 O(root(N))시간이 걸리는데, N개를 검사해야하므로 O(Nroot(N))의 시간이 걸리므로 너무 긴 시간이 걸린다.

에라토스테네스의 체는 다음과 같은 규칙으로 구한다.

  1. 2부터 N까지 모든 수를 써놓는다.

  2. 아직 지워지지 않은 수 중에서 가장 작은 수를 찾는다.

  3. 그 수는 소수이다.

  4. 이제 그 수의 배수를 모두 지운다.

이렇게 지우고 남아 있는 수가 모두 소수이다.

구현

  • 시간복잡도 : O(Nloglog(N))

    • n/2 + n/3 + n/4 + …. = loglog(N)

  • 주의할 점 i*i는 N의 범위에 따라서 i+i로 변경해준다.(백만이상일 경우 범위 초과)

M이상 N이하의 소수를 모두 출력하는 프로그램을 작성하시오.

증명이 되지 않은 문제여서 추측이라고 한다.

  • 2보다 큰 모든 짝수는 두 소수의 합으로 표현이 가능하다.

  • 5보다 큰 모든 홀수는 세 소수의 합으로 표현이 가능하다.

  • 10^18이하에서는 참인 것이 증명되어 있다.

소인수분해

정수 N을 소수의 곱으로 분해한 것이다.

  • 소수를 구하지 않고도 해결할 수 있다.

  • N을 소인수분해 했을 때, 나타날 수 있는 인수 중에서 가장 큰 값은 루트(N)이다.

팩토리얼

팩토리얼은 매우 큰 값이다.

03.Recursive에서 팩토리얼을 순환과 반복으로 풀어본 문제가 있다.

우리가 팩토리얼을 풀 수 있는 규모는 10! = 3628800 까지이다.

N!에서 0이 몇개인지 알아내는 문제이다.

  • ex) 10! = 3628800

0이 몇개인지는 N!를 소인수분해 해보면 알 수 있다.

  • 10! = 2^6 * 3^4 * 7 * (2^2 * 5^2)

하지만 실제로 구할 때 소인수분해를 다 할 필요는 없다. 5의 개수가 항상 2의 개수보다 적기 때문에 5의 개수만 세어주면된다.

N!의 0의 개수 = [N/5]+[N/5^2]+[N/5^3]+…

예를 들어 100!이면 (100/5 = 20) + (100/25) = 24개이다.

nCm의 끝자리 0의 개수를 구하는 문제이다. 팩토리얼에서는 2의 개수가 5의 개수보다 항상 많기 때문에 5만 세어줬지만, 조합은 어떻게 될지 모르기 때문에 2와 5의 개수를 모두 세어줘야한다.

Last updated

Was this helpful?