Doby's Lab

백준 14565번: 역원(Inverse) 구하기 (C++) 본문

PS/BOJ

백준 14565번: 역원(Inverse) 구하기 (C++)

도비(Doby) 2022. 6. 21. 22:59

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

 

14565번: 역원(Inverse) 구하기

집합 Zn을 0부터 n-1까지의 정수 집합이라고 하자. Zn ∋ a, b, c 일 때, (a+b) mod n = 0이면 b는 a의 덧셈역이라고 하고 (a*c) mod n = 1이면 c는 a의 곱셈역이라고 한다. 정수 N, A가 주어졌을 때 Zn에서의 A의

www.acmicpc.net


Solved By: EEA(Extended Euclidean Algorithm), MMI(Modular Multiplicative Inverse)

 

(곱셈역에 대한 풀이만 하겠습니다.)

확장 유클리드 알고리즘모듈러 연산 곱셈 역원에 대해 배우기 좋은 문제였습니다.

(a * c) = 1(mod n)이라는 식에서 a가 주어지면 c를 구해야 합니다.

다음 식은 a * c = 1 + n * y로 정리할 수 있고, 이는 a * c - n * y = 1 꼴로 나타내어 Diophantine Equation의 형태로 나타낼 수 있습니다.

 

a와 n의 gcd는 주어진 식에 따라 1을 나타내야 하기에 1이 아니라면 곱셈역은 존재하지 않는 걸로 하고, -1을 출력하게 해주었습니다.

그리고, 확장 유클리드 알고리즘에서는 r1의 값이 0이 되었을 때, s0값이 c의 값을 나타내기 때문에 이를 알고 c를 리턴하게 해주었습니다.

c는 Zn이라는 0부터 n - 1까지의 정수 집합에 속하며 음수 값이 나온다면 Modular 연산의 특징을 이용하여 리턴하게 해주었습니다.

#include <iostream>
#define ll long long
using namespace std;

ll N, A;

ll gcd(ll a, ll b){
    return b ? gcd(b, a % b) : a;
}

ll exGCD(ll a, ll b){
    ll r0 = a, r1 = b, s0 = 1, s1 = 0, t0 = 0, t1 = 1;
    ll q, r, s, t;
    
    while(true){
        ll q = r0 / r1; // int로 선언했어서 시간 초과 난 거임
        
        r = r0 - q * r1;
        r0 = r1;
        r1 = r;
        
        s = s0 - q * s1;
        s0 = s1;
        s1 = s;
        
        t = t0 - q * t1;
        t0 = t1;
        t1 = t;
        
        if(r1 == 0) break;
    }
    
    return (s0 % b + b) % b;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    cin >> N >> A;
    
    cout << N - A << ' ';
    
    if(gcd(A, N) != 1){
        cout << -1;
        return 0;
    }
    cout << exGCD(A, N);
    
    return 0;
}

 

728x90

'PS > BOJ' 카테고리의 다른 글

백준 2042번: 구간 합 구하기 (C++)  (0) 2022.06.25
백준 4233번: 가짜소수 (C++)  (0) 2022.06.25
백준 11256번: 사탕 (C++)  (0) 2022.06.19
백준 15720번: 카우버거 (C++)  (0) 2022.06.19
백준 14955번: How Many to Be Happy? (C++)  (0) 2022.06.18