math
나머지 연산
- (A+B) mod M = ((A mod M) + (B mod M)) mod M
- (AB) mod M = ((A mod M) (B mod M)) mod M
- 나누기의 경우 성립안함
- 뺄셈의 경우 먼저 mod 연산을 한 결과가 음수일 수 있음을 주의
- (A-B) mod M = ((A mod M) - (B mod M) + M) mod M
최대공약수 (GCD)
- 두 수의 공통된 약수 중 가장 큰 정수
가장 간단하게 구하는 방법: 2부터 min(A, B)까지 모든 정수로 나누어 보기 (O(N)의 시간복잡도)
1
2
3
4
5
6int g = 1;
for(int i = 2; i < min(A, B); i++){
if(a % i == 0 && b % i == 0) {
g = i;
}
}유클리드 호제법을 사용하면 빠르게 구할 수 있음
- a, b를 나눈 나머지 r
- GCD(a, b) = GCD(b, r)
- r이 0이면 그 떄의 b가 최대공약수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//재귀함수 사용한 방법
//a < b라고 해서 a, b를 swap 시킬 필요없음
int gcd(int a, int b) {
if(b == 0) {
return b;
}
else {
return gcd(b, a%b);
}
}
//반복문을 사용한 방법
//O(lgN)의 시간복잡도
int gcd(int a, int b) {
while(b != 0) {
int r = a%b;
a = b;
b = r;
}
return a;
}
최소공배수 (LCM)
- 두 수의 공통된 배수 중 가장 작은 정수
- GCD를 이용해 구할 수 있음
- A B = GCD LCM
소수
- 약수가 1과 자기 자신 밖에 없는 수
관련 알고리즘1 : 어떤 수 N이 소수인지 아닌지 판별
2부터 N-1까지 나누어서 확인
1
2
3
4
5
6
7
8
9
10
11
12//O(N)
bool prime(int n) {
if(n < 2){
return false;
}
for(int i = 2; i < n - 1; i++) {
if(n % i == 0){
return false;
}
}
return true;
}2부터 N/2까지 나누어서 확인 (약수 중 가장 큰 수는 N/2보다 작거나 같기 때문)
1
2
3
4
5
6
7
8
9
10
11
12//O(N)
bool prime(int n) {
if(n < 2){
return false;
}
for(int i = 2; i < n/2; i++) {
if(n % i == 0){
return false;
}
}
return true;
}2부터 루트N까지 나누어서 확인 (N = a * b 일 때, a <= 루트N, b >= 루트N 이기 때문)
1
2
3
4
5
6
7
8
9
10
11
12//O(루트N)
bool prime(int n) {
if(n < 2){
return false;
}
for(int i = 2; i*i <= n; i++) {
if(n % i == 0){
return false;
}
}
return true;
}
관련 알고리즘2 : N이하의 소수를 찾는 방법
- 1부터 N까지 소수인지 아닌지 하나씩 확인, O(N*루트N)
- 에라토스테네스의 체 (가장 빠른 방법)
1
2
3
4
5
6
7
8
9
10
11
12
13int prime[100]; //소수 저장
int pn = 0; //소수의 개수
bool check[101]; //지워졌으면 true
int n= 100;
for(int i = 2; i <= n; i++) {
if(check[i] == false){
prime[pn++] = i;
for(int j = i*i; j <= n; j += i) {
check[j] = true;
}
}
}
//안쪽의 for문에서 i*i가 i=1,000,000일 경우 int의 표현범위인 21억을 넘기 때문에 문제가 있을 수도 있어 i*2, i+i와 같이 바꾸는 것이 좋음
골드바흐의 추측
- 2보다 큰 모든 짝수는 두 소수의 합으로 표현 가능하다.
- 위 문장에 3을 더하면 5보다 큰 모든 짝수는 세 소수의 합으로 표현 가능하다.
- 10^18 이하에서는 참으로 증명됨
- N = a + b (a, b는 소수)를 구할 때, 에라토스테네스의 체를 사용해 범위 내의 모든 소수(a)를 구한 뒤, N - b가 소수인지 판별하는 방식으로 구할 수 있다. N - b가 소수인지 아닌지는 check배열로 검사하면 된다.
팩토리얼
- N! = 1 2 … * N
- 10! = 3628800
관련 연습문제
- GCD 합 (9613)
- 숨바꼭질 6 (17087)
- 2진수 8진수 (1373)
- 8진수 2진수 (1212)
- -2진수 (2089)
- 골드바흐 파티션 (17103)