TeddysRoom / Algo-rhythm

유 슡 쳌 마 알고-리듬 :notes:
6 stars 0 forks source link

Mathematics #10

Closed MUKER-WON closed 2 months ago

MUKER-WON commented 2 months ago

9/25 링크

stealmh commented 2 months ago

수학

소수

1과 자신으로만 나눠지는 수 즉 약수가 2개인 수를 말한다. 2부터 n-1까지의 수로 나누어지지 않는 수

1은 소수가 아니다.

합성수 1과 자기 자신을 제외한 다른 약수를 가지고 있는 수

연산이 최대 n-2번 발생하기때문에 시간복잡도는 O(n) 이 시간복잡도를 O(sqrt(n))으로 줄일 수 있는 방법이 있다

합성수 N에서 1을 제외한 가장 작은 약수는 sqrt(N) 이하이다. N이 9라면, sqrt(9)는 3이다. 가장 작은약수는 3이하고 1,3,9중 1을 제외한 가장 작은 약수는 3이 됨

따라서 2부터 n-1까지의 수로 나누어지지 않는 수를 지금까지 소수라고 했다면 O(n) 2부터 sqrt(n)까지의 수로 나누어지지 않으면 소수이다. O(sqrt(n))

연습문제

1978: 소수찾기

코드 ```swift var primeCount: Int = 0 let n = Int(readLine()!)! let listup = readLine()!.split(separator: " ").map { Int($0)! } for i in listup { if isPrime(i) { primeCount += 1 } } func isPrime(_ num: Int) -> Bool { if num == 1 { return false } for i in 2...num where i * i <= num { if num % i == 0 { return false } } return true } print(primeCount) ```
MUKER-WON commented 2 months ago

수학 (Mathematics)

소수

sqrt() 함수를 사용하면 안될까?

에라토스테네스의 체

func sieveOfEratosthenes(_ n: Int) -> [Int] {
    // 0부터 n까지의 값을 가진 배열을 true로 초기화 (소수인지 여부를 나타냄)
    var isPrime = [Bool](repeating: true, count: n + 1)
    isPrime[0] = false // 0은 소수가 아님
    isPrime[1] = false // 1도 소수가 아님

    // 2부터 sqrt(n)까지의 수들에 대해
    for i in 2...Int(Double(n).squareRoot()) {
        if isPrime[i] {
            // i의 배수들을 소수가 아니라고 표시
            for multiple in stride(from: i * i, through: n, by: i) {
                isPrime[multiple] = false
            }
        }
    }

    // 소수인 수들만 배열로 반환
    return (2...n).filter { isPrime[$0] }
}

let primes = sieveOfEratosthenes(50)
print(primes)

소인수분해

import Foundation

func optimizedPrimeFactorization(_ n: Int) {
    var n = n

    // 먼저 2로 나누기
    while n % 2 == 0 {
        print(2)
        n /= 2
    }

    // 3부터는 홀수만 체크 (i += 2)
    var i = 3
    while i * i <= n {
        while n % i == 0 {
            print(i)
            n /= i
        }
        i += 2
    }

    // n이 1보다 크면 마지막 소수 출력
    if n > 1 {
        print(n)
    }
}

let n = Int(readLine()!)!
optimizedPrimeFactorization(n)

최대공약수(Greatest Common Divisor, GCD)

유클리드 호제법

func gcd(_ a: Int, _ b: Int) -> Int {
    return a == 0 ? b : gcd(b % a, a)
}

최소공배수(Lowest Common Multiple, LCM)

func lcm(_ a: Int, _ b: Int) -> Int {
    return (a * b) / gcd(a, b)
}

// 오버플로우가 걱정된다면 해당 코드로 구현 가능
func lcm(_ a: Int, _ b: Int) -> Int {
        return a / gcd(a, b) * b
}

연립합동방정식

중국인의 나머지 정리

// 모듈로 역수를 구하는 함수
func modInverse(_ a: Int, _ m: Int) -> Int {
    var m0 = m
    var y = 0, x = 1

    if m == 1 {
        return 0
    }

    var a = a
    while a > 1 {
        let q = a / m
        var t = m

        m = a % m
        a = t
        t = y

        y = x - q * y
        x = t
    }

    if x < 0 {
        x += m0
    }

    return x
}

// 중국인의 나머지 정리 함수
func chineseRemainder(_ nums: [Int], _ rems: [Int]) -> Int {
    let prod = nums.reduce(1, *)
    var result = 0

    for i in 0..<nums.count {
        let pp = prod / nums[i]
        result += rems[i] * modInverse(pp, nums[i]) * pp
    }

    return result % prod
}

// 테스트 예시
let nums = [3, 5, 7]   // 모듈로들
let rems = [2, 3, 2]   // 나머지들

let result = chineseRemainder(nums, rems)
print("\(result)")

이항계수

// 재귀적으로 이항계수 계산
func BCR(n: Int, k: Int) -> Int {
    if k == 0 || k == n { return 1 }
    return BCR(n: n - 1, k: k - 1) + BCR(n: n - 1, k: k)
}

// 예시
let resultRecursive = BCR(n: n, k: k)
print("C(\(n), \(k)) = \(resultRecursive)")  // 출력: C(5, 2) = 10

문제 풀이

백준 11051번: 이항 계수2

let I = readLine()!.split { $0 == " " }.map { Int($0)! }
let (N,K) = (I[0],I[1])
var dp = Array(repeating: Array(repeating: 0, count: N+1), count: N+1)

for i in 0...N {
    for j in 0...min(i,K) { // 불필요한 반복을 줄이기 위해 i,k중 작은값 까지 반복
        if j == 0 || j == i { dp[i][j] = 1 }
        else { dp[i][j] = (dp[i-1][j-1] + dp[i-1][j]) % 10007 }
    }
}
print(dp[N][K])
qwerty3345 commented 2 months ago

수학 알고리즘

1. 소수 (Prime Numbers)

1.1 소수의 정의

1.2 소수 판정 알고리즘

1.3 에라토스테네스의 체

2. 최대공약수 (GCD)와 최소공배수 (LCM)

2.1 약수

2.2 최대공약수 (GCD)

2.3 최소공배수 (LCM)

3. 연립합동방정식

3.1 개념

3.2 해결 방법

3.3 중국인의 나머지 정리 (CRT)

4. 이항계수

4.1 정의

4.2 계산 방법

4.3 큰 수의 이항계수 계산

주의사항

BOJ 6064 카잉 달력

import Foundation

let inputNum = Int(readLine()!)!

func solution(M: Int, N: Int, x: Int, y: Int) -> Int {
    let lcm = lcm(M, N)
    var year = x

    while year <= lcm {
        if (year - 1) % N + 1 == y {
            return year
        }
        year += M
    }
    return -1
}

func gcd(_ a: Int, _ b: Int) -> Int {
    return b == 0 ? a : gcd(b, a % b)
}

func lcm(_ a: Int, _ b: Int) -> Int {
    return a / gcd(a, b) * b
}

let result: [Int] = (0..<inputNum).map { _ in
    let input = readLine()!.components(separatedBy: " ").compactMap { Int($0) }
    return solution(M: input[0], N: input[1], x: input[2], y: input[3])
}
result.forEach {
    print($0)
}
shippingpark commented 2 months ago

소수판정법에서의 Tip

루트 N 범위를 잡을 때 루트 연산자를 쓰면 실수 연산자라 오차가 발생할 수 있음 for 문의 조건에서 i*i<=N 이라고 두면 됌

소인수분해 문제 풀이

import Foundation

var n = Int(readLine()!)!
var i = 3

func division() {
  guard n > 1 else { return }
  while n%2 == 0 {
    print("2")
    n /= 2
  }

  while i*i<=n {
    if n%i==0 {
      print(i)
      n /= i
    } else {
      i += 2
    }
  }

  if n > 1 {
    print(n)
  }
}

division()

수학 문제는 많이 나오지 않지만, 기본 개념을 숙지할 것

소수:

소수는 1과 자기 자신으로만 나누어지는 수이다. 합성수에서 1을 제외한 가장 작은 약수는 √N 이하이므로, 소수를 구할 때 N-1까지 나누지 않고 √N까지만 나누어도 소수인지 판단할 수 있다.

에라토스테네스의 체:

2부터 N까지의 소수를 구하는 알고리즘으로, 배수를 제거하는 방식이다. 소수를 빠르게 구할 수 있는 방법으로 사용된다.

소인수분해:

정수를 소수의 곱으로 나타내는 것을 의미한다. 예를 들어, 1100 = 2 2 5 5 11로 표현된다.

최대공약수(GCD):

두 자연수의 공통된 약수 중 가장 큰 약수로, 유클리드 호제법을 사용하여 구할 수 있다.

최소공배수(LCM):

두 자연수의 공통 배수 중 가장 작은 수로, GCD를 이용하여 LCM을 구할 수 있다.

연립합동방정식:

여러 개의 합동식을 동시에 만족하는 값을 구하는 문제이다. 중국인의 나머지 정리를 통해 해를 구할 수 있으며, 모듈로 값들이 서로소일 때 유용하다.

이항계수:

n개의 원소 중 k개의 원소를 선택하는 방법의 수를 나타낸다. 이항계수는 재귀 함수나 파스칼의 법칙을 이용해 계산할 수 있다.