Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Be Coder

수학 - 나머지 연산, GCD, LCM, 진법, 소수 본문

알고리즘

수학 - 나머지 연산, GCD, LCM, 진법, 소수

ForzaCoding 2020. 4. 16. 22:13

● 나머지 연산

> (A + B) mod M = ((A mod M) + (B mod M)) mod M

> (A * B) mod M = ((A mod M) * (B mod M)) mod M

> 나누기의 경우는 성립되지 않음.

> (A - B) mod M = ((A mod M) - (B mod M) + M) mod M

     - 뺄셈의 경우에는 마이너스가 나올 수 있기 때문에 M을 더해주어야 한다.

 

 

● GCD(최대공약수) - 유클리드 호제법

> 최대공약수를 구하는 가장 쉬운 방법은 2부터 min(A, B)까지 모든 정수로 나눠보는 것이다.

> 하지만, 속도를 높이기 위해 유클리드 호제법을 사용한다.

    - a%b가 r이라고 할때, GCD(a, b) = GCD(b, r)이다.

    - r이 0이면, 그 때의 b가 최대공약수가 된다.

// 재귀함수를 사용하지 않는 유클리드 호제법

int gcd(int x, int y){
    while(y != 0){
    	int r = x % y;
        x = y;
        y = r;
    }
    return x;
}



// 재귀함수를 사용한 유클리드 호제법

int gcd(int x, int y){
    if(y == 0) return x;
    else return gcd(y, x % y);
}

    - 세 수의 최대공약수는 GCD(a, b, c) = GCD(GCD(a, b), c)로 구하면 된다. N개의 최대공약수를 구할때 이를 반복해서 구한다.

 

● LCM - 최소공배수

> GCD를 응용하면 된다.

> A, B 두 숫자와 두 숫자의 GCD가 R일때, LCM = R * (A / R) * (B / R) 이다. 

 

 

● 진법 변환

> 10진법 숫자 N을 B진법으로 바꾸면 그냥 N이 0이 될 때까지 나누기만 하면 된다.

> B진법 숫자 N을 10진법으로 바꾸려면 숫자 한자리마다 B^k를 곱하며 더하면 된다.

> A진법을 B진법으로 바꾸려면, A진법 -> 10진법 -> B진법으로 바꾸면 된다.

// B진법을 10진법으로 바꾸는 코드

#include <iostream>
#include <string>
using namespace std;
int main() {
    int ans = 0;
    string s;
    int b;
    cin >> s >> b;
    for (int i=0; i<s.size(); i++) {
        if ('0' <= s[i] && s[i] <= '9') {
            ans = ans * b + (s[i] - '0');
        } else {
            ans = ans * b + (s[i] - 'A' + 10);
        }
    }
    cout << ans << '\n';
}

 

● 소수

> 소수는 1과 자신만 약수로 가진다.

> N이 소수가 되려면, 2보다 크고, 루트N보다 작거나 같은 자연수로 나눠 떨어지면 안된다. 

    - N이 소수가 아니라면 N = a * b로 나타낼 수 있는데, a * b의 차이가 가장 작은 경우가 루트N이다.

      그렇기 때문에 루트N까지만 검사하면된다.

// 소수 구하는 가장 쉬운 구현
// 시간 복잡도는 O(루트N)

bool prime(int x){
    if(x < 2) return false;
    
    for(int i = 2; i * i <= x; i++)
        if (x % i == 0) return false;
        
    return true;
}

 

> 하지만 N의 범위가 커지면, 시간이 너무 오래걸리게 된다. 이 경우, 에라토스테네스의 체를 사용한다.

에라토스테네스의 체는 배열에서 i의 배수를 모두 지워나간다.

// 에라토스테네스의 체 구현

const int MAX = 1000000;
bool check[MAX + 1]; // true: 소수가 아님, false: 소수
void Eratosthenes(){
    check[0] = check[1] = true;
    for(int i = 2; i*i <= MAX; i++) {
        if(check[i] == false) {
            for(int j = i + i; j <= MAX; j += i) {
                check[j] = true;
            }
        }
    }
}

 

- 골드바흐의 추측

> 2보다 큰 모든 짝수는 두 소수의 합으로 나타낼 수 있다.

> 5보다 큰 모든 홀수는 세 소수의 합으로 나타낼 수 있다.

> 아직 증명되지는 않았지만, 10^18까지는 유효하다.

> 에라토스테네스의 채를 이용하여 구현하면 된다.

 

● 소인수분해

> 정수 N을 소수의 곱으로 분해하는 것. 소수를 구하지 않고도 구현 가능하다.

> N을 소인수분해 했을 때, 나타날 수 있는 인수 중 가장 큰 값은 루트N이다.(즉, i*i <= N까지만 돌면 된다.)

// 소인수분해 구현

for(int i = 2; i*i <= n; i++){
	while(n % i == 0){
    	cout << i;
        n /= i;
    }
}

// i는 n의 인수.

'알고리즘' 카테고리의 다른 글

[프로그래머스] 다트게임  (0) 2020.05.14
[프로그래머스] 징검다리 건너기  (0) 2020.05.05
[프로그래머스] 호텔 방 배정  (0) 2020.05.05
불량사용자  (0) 2020.04.30
튜플  (3) 2020.04.30