| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- c++ 코테
- 개발자취업
- 파이썬
- C++
- 뷰
- react
- 오블완
- DP
- 코딩테스트
- 파이썬 코테
- 코테
- 백준
- vue
- Laravel
- Flutter
- 플러터
- 항해99
- 코딩테스트 준비
- 티스토리챌린지
- 개발자 취업
- 코딩테스트준비
- 99클럽
- 코테 파이썬
- til
- Python
- flutter getx
- 안드로이드
- 라라벨
- ML
- 알고리즘
- Today
- Total
잡다로그
[C++/코테] 수학 본문
소수
- 1과 자기 자신으로만나누어지는 수. ↔ 합성수
1은 소수도 합성수도 아니다! - 약수가 2개인 수
- 2부터 N-1까지의 수로 나누어지지 않는 수 → 시간 복잡도가 $O(N)$
1. 소수 판정법
합성수 N에서 1을 제외한 가장 작은 약수는 ${\sqrt N}$
ex) N = 18 → 2 ≤ $\sqrt 18$
ex) N = 25 → 5 ≤ $\sqrt 25$
ex) N = 21 → 3 ≤ $\sqrt 21$
즉, 2부터 $\sqrt N$까지의 수로 나누어지지 않으면 소수임을 알 수 있음. 시간 복잡도 $O(\sqrt N)$ 소요
bool isprime(int n){
if(n == 1) return 0;
for (intn i = 2; i*i < n; i++){
if(n % i == 0) return 0;
}
return 1;
}
실수의 저장/연산 과정에서의 오차 때문에 sqrt 함수를 사용할 수 없다. 대신 조건문에 i * i 를 해준다.
연습문제
백준 1978: 소수 찾기 https://www.acmicpc.net/problem/1978
2. 범위 내에서의 소수 판정법
(1) 범위 내의 각각 숫자들이 소수인지 판정
vector<int> primelist(int n){
vector<int> primes;
for (int i = 2; i <= n; i++){
bool isprime = 1;
for (int j = 2; j*j <= i; j++){
if(i % j == 0){
isprime = 0;
break;
}
}
if (isprime) primes.push_back(i);
}
return primes;
}
# 개선 ver. 2부터 루트 N까지의 범위에서만 나눠준다.
vector<int> primelist(int n){
vector<int> primes;
for (int i = 2; i <= n; i++){
bool isprime = 1;
for (int p: primes){
if(p*p > i) break;
if (i % p == 0){
isprime = 0;
break;
}
}
if (isprime) primes.push_back(i);
}
return primes;
}
(2) 에라토스테네스의 체
k를 제외한 k의 배수들을 모두 거르며 (False로 만든다.) 합성수를 제거해 나가는 방법
vector<int> sieve(int n){
vector<int> primes;
vector<bool> state(n+1, true);
state[1] = false; // 1은 소수가 아니다.
for (int i = 2; i <= n; i++){
if(!state[i]) continue;
for (int j = i*i; j <= n; j += i){
state[j] = false;
}
}
for (int i =2; i <= n ; i++){
if (state[i]) primes.push_back(i);
}
return primes;
}
배열이 아닌 vector로 두면 저장 공간을 8배 정도 절약하는 최적화 코드를 짤 수 있다.
연습문제
백준 1929: 소수 구하기 https://www.acmicpc.net/problem/1929
3. 소인수분해
- 정수를 소수의 곱으로 나타내는 것
- 모든 자연수는 소인수분해하는 방법이 하나뿐이다.
연습문제 _소인수분해 구현
백준 11653: 소인수분해 https://www.acmicpc.net/problem/11653
#include <bits/stdc++.h>
using namespace std;
int main(void){
ios::sync_with_stdio(0);
sin.tie(0);
int n;
cin >> n;
for (int i = 2; i*i <= n; i++){
while(n%i == 0){
cout << i << '\n';
n \= i;
}
}
if (n != 1) cout << n;
}
- 에라토스테네스의 체를 사용한다.
i = 2부터 시작하여 주어진 수 (N)을 반복적으로 나눈다. 나누어 떨어지지 않으면 i를 1 증가시키고, 나누기를 반복. - N이 전부 나누어떨어져서 1이 될 때 종료 → $O(N)$ 시간복잡도
i * i > N 일 때 종료 → $O(\sqrt N)$ 시간복잡도 (* 상단 소수판정법 참고)
최대공약수
- 약수: 어떤 수를 나누어 떨어지게 하는 수
vector<int> divisor(int n){
vector<int> div;
for (int i = 1; i*i <= n; i++){
if(n%i == 0) div.push_back(i);
}
for (int j = (int)div.size() - 1; j >= 0; j--){ // div.size() - 1 : 약수 목록을 크기 순으로 저장하기 위해
if(div[j] * div[j] == n) continue;
div.push_back(n / div[j]);
}
return div;
}
- 최대공약수(GCD): 두 자연수의 공통된 약수 중 가장 큰 약수
- 유클리드 호제법 - 두 수 A, B에 대해서 A를 B로 나눈 나머지를 r이라고 하면 GCD(A, B) = GCD(B, r)이다.
ex) GCD(20, 12) = GCD (12, 8) = GCD(8, 4) = GCD(4, 0) = 4
int gcd(int a, int b){
if(a == 0) return b;
return gcd(b%a, a);
}
- 최소공배수(LCM): A $\times$ B = GCD(A, B) $\times$ LCM(A, B)
int lcm(int a, int b){
return a/ gcd(a, b) * b; // a* b/gcd(a,b) 가 아닌 이유 int overflow 방지
}
연립합동방정식
연습문제
백준 6064 카잉달력 https://www.acmicpc.net/problem/6064
이항계수

색이 다른 공 n개중에서 k개를 선택,
순열 - 순서를 고려한 뽑기 $_nP_k$
조합 - 순서를 고려하지 않은 뽑기 $_nC_k$
연습문제
백준 11050: 이항계수1 https://www.acmicpc.net/problem/11050
백준 11051: 이항계수2 https://www.acmicpc.net/problem/11051
- $_nC_k = n- _1Ck + n - _1C_k - 1$ 라는 조합의 성질이 자주 쓰인다. DP로 구현 가능하다.
출처:
[실전 알고리즘] 0x12강 - 수학
안녕하세요 여러분, 즐거운 수학 시간입니다. 비록 수학에 대한 원초적인 두려움을 가지고 있는 분이 많다는건 잘 알고 있지만 여기서 말하는 수학이라고 하는게 코딩테스트에서 수학이라는 문
blog.encrypted.gg
'Algorithm' 카테고리의 다른 글
| [Python/코테] 백준 4948 베르트랑 공준 (0) | 2023.12.02 |
|---|---|
| [Python/코테] 소수 판별, 에라토스테네스의 체 (0) | 2023.12.01 |
| [Python/코테] 백준 1912 연속합 (0) | 2023.11.27 |
| [Python/코테] 백준 1181 단어 정렬 (0) | 2023.11.27 |
| [Python/코테] 백준 11726 2xn 타일링 (0) | 2023.11.27 |