Algorithm/Baekjoon

[λ°±μ€€] (Swift) 17425번 - μ•½μˆ˜μ˜ ν•©

감자 πŸ₯” 2022. 12. 23. 13:00
λ°˜μ‘ν˜•

이게 μ™œ κ³¨λ“œμ§€? ν–ˆλ‹€κ°€ μ•„μ£Όκ·Έλƒ₯ ν˜Έμ˜€μ˜¨λ‚¬λ˜ 문제!!

 

🟠 문제

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

 

17425번: μ•½μˆ˜μ˜ ν•©

두 μžμ—°μˆ˜ A와 Bκ°€ μžˆμ„ λ•Œ, A = BCλ₯Ό λ§Œμ‘±ν•˜λŠ” μžμ—°μˆ˜ Cλ₯Ό A의 μ•½μˆ˜λΌκ³  ν•œλ‹€. 예λ₯Ό λ“€μ–΄, 2의 μ•½μˆ˜λŠ” 1, 2κ°€ 있고, 24의 μ•½μˆ˜λŠ” 1, 2, 3, 4, 6, 8, 12, 24κ°€ μžˆλ‹€. μžμ—°μˆ˜ A의 μ•½μˆ˜μ˜ 합은 A의 λͺ¨λ“  μ•½μˆ˜λ₯Ό 더

www.acmicpc.net

뭐야! 이전에 ν’€μ—ˆλ˜ 'μ•½μˆ˜μ˜ν•©2'λ¬Έμ œλž‘ λ˜‘κ°™μž–μ•„? 근데 κ·Έλƒ₯ , μž…λ ₯만 λ‹€λ₯΄κ²Œ ν•˜λ©΄ λ˜λŠ”κ±°μž–μ•„!!!

 

🟠 μ‹œκ°„μ΄ˆκ³Ό ^___^

심지어 μž…λ ₯ 방식도 잘λͺ»μ•Œμ•˜λ‹€. μ΄ˆλ°˜μ— μž…λ ₯λ˜λŠ” 5λ₯Ό λͺ»λ³΄κ³ , κ·Έλƒ₯ 끝없이 μž…λ ₯이 κ°€λŠ₯ν•œ? λ¬Έμ œμΈμ€„ μ•Œκ³  while으둜 μž‘μ„±ν–ˆλ‹€.

while let N = Int(readLine()!) {
    print(solution(N))
}

private func solution(_ N: Int) -> Int {
    let N = N ?? 0
    var sum = 0

    for i in 1..<N+1 {
        sum += (N / i) * i
    }

    return sum
}

μ—₯,, μ‹œκ°„μ΄ˆκ³Όλ„€? 일단, μ΄ˆλ°˜μ— N개λ₯Ό μž…λ ₯ν• κ±°λΌλŠ” Tλ₯Ό μž…λ ₯λ°›μ•˜μ–΄μ•Όν–ˆλŠ”λ°, λ‚˜λŠ” 끝없이 μž…λ ₯이 κ°€λŠ₯ν•˜κ²Œ μ½”λ“œλ₯΄ μž‘μ„±ν•΄μ„œ 틀린쀄 μ•Œμ•˜λ‹€. 근데 ,, μ΄λ¬Έμ œλ„ μ•„λ‹ˆμ—ˆλ‹€.!!

μž…λ ₯을 μ œλŒ€λ‘œ 받아도 μ‹œκ°„μ΄ˆκ³Όμ˜€λ‹€.

πŸ”– 해결방법을 μƒκ°ν•΄λ³΄μž

μš°μ„ , 예제λ₯Όλ³΄λ©΄, T = 5 을 μž…λ ₯λ°›λŠ”λ‹€. λ‚΄ μ½”λ“œλ₯Ό 보면, λ§Œμ•½ 5λ²ˆμ„ μž…λ ₯λ°›μœΌλ©΄, 5번 λͺ¨λ‘ g(N)을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄μ„œ 연산을 λ°˜λ³΅ν•œλ‹€.

μ˜ˆμ œμƒν™©μœΌλ‘œ 생각해보면
g(1) 을 κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ f(1) κ΅¬ν•˜κ³  sum인 f(1) ꡬ함
g(2) λ₯Ό κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ f(1), f(2) κ΅¬ν•˜κ³  sum 인 f(1) + f(2) ꡬ함
g(10)을 κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ f(1), f(2), f(3), f(4), f(5)....f(10) κ΅¬ν•˜κ³ , sum 인 f(1)+f(2)+f(3)+...+f(10) ꡬ함
.......
μ΄λ ‡κ²Œ λ°˜λ³΅λœλ‹€.

μ“Έλ°μ—†λŠ” 연산이 λ§Žμ•„μ‘Œλ‹€. f(2)λ₯Ό 이전에 κ΅¬ν•΄λ†¨λŠ”λ°, 이λ₯Ό μž¬μ‚¬μš©ν•  순 μ—†μ„κΉŒ? 또, μ§€κΈˆ μ˜ˆμ œμ—μ„œλ§Œ 이정도지, λ§Œμ•½ T = 100000 을 μž…λ ₯λ°›κ²Œ 되면, 10λ§Œλ²ˆμ„ μ—°μ‚°ν•΄μ€˜μ•Όν•œλ‹€. 이 연산을 쀄이기 μœ„ν•΄μ„œλŠ”,,, dp ν˜•νƒœλ‘œ λ§Œλ“€μ–΄μ€˜μ•Όκ² λ‹€κ³  νŒλ‹¨ν–ˆλ‹€.

즉, λͺ¨λ“  닡을 미리 ꡬ해놓고, λ§ˆμ§€λ§‰μ— μž…λ ₯λ°›λŠ” i 에 λŒ€ν•΄μ„œ dp[i]λ₯Ό λ°”λ‘œ 좜λ ₯ν•  수 μž‡κ²Œ λ§Œλ“€μ–΄ λ†“λŠ” 것이닀.

[ f(1), f(1)+f(2), f(1)+f(2)+f(3), f(1)+f(2)+f(3)+f(4), ,,,,,,, f(1)+..+f(100000) ]

μ΄λ ‡κ²Œ κ΅¬ν•΄λ³΄μž.

🟠 첫번째 μ‹œλ„

μ΄λ ‡κ²Œ μ½”λ“œλ₯Ό μž‘μ„±ν–ˆλ‹€. 

[ f(1), f(1)+f(2), f(1)+f(2)+f(3), f(1)+f(2)+f(3)+f(4), ,,,,,,, f(1)+..+f(100000) ]

이 ν˜•νƒœλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œ, divλΌλŠ” 배열을 λ§Œλ“€μ—ˆκ³ , divλŠ” i의 μ•½μˆ˜μ˜ 합을 λ„£μ–΄λ‘” 것이닀. 이 λ©”μ„œλ“œλ₯Ό κ΅¬ν•˜λŠ” 것에 λŒ€ν•΄μ„œλ„ 생각이 쑰금 ν•„μš”ν–ˆλŠ”λ°, 인터넷을 쑰금 ,, λ’€μ Έλ΄€λ‹€ 미리 κ΅¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” 1의 λ°°μˆ˜μ— 1μ”© 더해주고, 2의 λ°°μˆ˜μ—λŠ” 2λ₯Ό 더해주고, 3의 λ°°μˆ˜μ—λŠ” 3을 더해주고,,, μ΄λŸ°μ‹μœΌλ‘œ 100λ§ŒκΉŒμ§€ 각 i의 μ•½μˆ˜μ˜ 합을 κ΅¬ν•΄μ£Όμ—ˆλ‹€. κ·Έ 배열이 λ°”λ‘œ div

그리고 sum 배열은 λˆ„μ ν•©μ„ κ΅¬ν•΄μ£Όμ—ˆλ‹€. 

 

private func solution() {
    let accumulate = accumulateSum()
    let T = Int(readLine()!)!

    for _ in 0..<T {
        let num = Int(readLine()!)!
        print(accumulate[num])
    }
}

private func accumulateSum() -> [Int] {
    var div = Array(repeating: 0, count: 1000000)
    var sum = Array(repeating: 0, count: 1000000)

    for i in 1...1000000 {
        var j = 1
        while i*j < 1000000 {
            div[i*j] += j
            j += 1
        }
    }
    sum[1] = div[1]
    for i in 2..<div.count {
        sum[i] = sum[i-1] + div[i]
    }

    return sum
}

solution()

읭

λŸ°νƒ€μž„μ—λŸ¬..? μ–΄λ”” μ˜ˆμ™Έλ₯Ό λͺ»μž‘μ•˜λ‚˜λ³΄λ‹€.. λ„λŒ€μ²΄ 뭘까!

 

🟠 μ •λ‹΅ μ½”λ“œ

λŸ°νƒ€μž„ μ—λŸ¬μ˜ λ¬Έμ œλŠ” λ²”μœ„μ˜€λ‹€. 

    var div = Array(repeating: 0, count: 1000000)
    var sum = Array(repeating: 0, count: 1000000)
    
    while i*j < 1000000 { .. }

div 와 sum을 μ΄λ ‡κ²Œ μ„€μ •ν•΄μ£Όκ³  while문을 1000000 미만으둜 μ„€μ •ν•΄μ£Όμ—ˆλ‹€. μ΄λ ‡κ²Œ ν•˜κ²Œ λ˜λ‹ˆκΉŒ, N의 μ΅œλŒ€κ°’μΈ 1000000을 μž…λ ₯ν•  수 μ—†μ—ˆλ‹€. κ·Έλž˜μ„œ λ²”μœ„λ₯Ό μ‘°μ ˆν•΄μ£Όλ©΄μ„œ λŸ°νƒ€μž„μ—λŸ¬λ₯Ό ν•΄κ²°ν–ˆλ‹€!

private func solution() {
    let accumulate = accumulateSum()
    let T = Int(readLine()!)!

    for _ in 0..<T {
        let num = Int(readLine()!)!
        print(accumulate[num])
    }
}

private func accumulateSum() -> [Int] {
    var div = Array(repeating: 0, count: 1000001)
    var sum = Array(repeating: 0, count: 1000001)

    for i in 1...1000000 {
        var j = 1
        while i*j <= 1000000 {
            div[i*j] += j
            j += 1
        }
    }
    sum[1] = div[1]
    for i in 2..<div.count {
        sum[i] = sum[i-1] + div[i]
    }

    return sum
}

solution()

λ°˜μ‘ν˜•