The sum of the squares of the first ten natural numbers is,
12 + 22 + ... + 102 = 385
The square of the sum of the first ten natural numbers is,
(1 + 2 + ... + 10)2 = 552 = 3025
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
The brute-force algorithm for this is pretty simple, just run a loop and calculate the result:
(def N 101) (defn square [x] (* x x)) (println (- (square (reduce + (range 1 N))) (->> (range 1 N) (map square) (reduce +))))This runs pretty fast (note that the JVM takes 1.5s to start up on my machine):
$ time clj 6.clj 25164150 real 0m1.517s user 0m3.001s sys 0m0.133sWe can do better though. As we saw in Problem 001, we can use a formula to calculate the sum of numbers from 1 to $N$:
$$
\sum^n_{i=1} i = \frac{n(n+1)}{2}
$$
Or in Clojure:
(defn sumto [n] (quot (* n (+ n 1)) 2))If we square this value, we get the square of the sums (the first value in our subtraction). This is O(1) rather than O(n).
Turns out there is also a formula for the sum of squares of a sequence:
$$
\sum^n_{i=1} i^2 = \frac{n(n+1)(2n+1)}{6}
$$
For more details, see here.
Writing this out in Clojure:
(defn sumto-sq [n] (quot (* n (+ n 1) (+ (* 2 n) 1)) 6))Combining them all together:
(def N 100) (println (- (square (sumto N)) (sumto-sq N)))This also runs fast, and should run fast for any number that fits into a 64-bit integer1:
$ time clj 6.clj 25164150 real 0m1.583s user 0m3.043s sys 0m0.140s
1 We may have to algebraically manipulate the formula a bit to avoid overflows but it should be doable.↩
No comments:
Post a Comment