[Project Euler] 歐拉項目練習題001
周銀輝
關於Project Euler的一點介紹:
哈哈,兩個月沒更新部落格了,因為跑去做Project Euler上的練習題了,非常非常樂意向大家推薦這個網站:http://projecteuler.net/ 上面有很多題,由淺入深,基本上是由數學與電腦程式相結合來解決問題,非常有意思。另外建議大家在編程時選用C語言,以及盡量不要用庫函數(malloc之類少數函數還是必須得使用的)以更好地提高自己的編程能力。當然肯定會有同學會提ACM之類的,恩,蘿蔔白菜各有所愛啦,反正我更愛Project Euler. 還有就是要持之以恒,我看了下,有十多萬註冊,但從level 0(沒有層級)到level 1就只有20%人的堅持下來,更不要說level 6啦,不過還是很多大牛到達了這個層級,並且也不乏中國紅旗哈,很值得驕傲。
第一題:
描述:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
(先思考,如果有興趣先編程試試,然後才看下面的內容)
分析:
由於是第一題,所以非常簡單,我稍稍分析一下
我們可以看看不超過20的數中3,5的倍數列表:3, 5, 6, 9, 10, 12, 15, 18, 20
很明顯其可以撤成兩類 3, 6, 9, 12, 15, 18 和 5, 10, 15, 20
他們分別是以3為首項3為等差的等差數列 以及 以5為首項5為等差的等差數列。或者理解成3的倍數的數列,以及5的倍數的數列。
哦,原來題目要求是兩個等差數列求和,然後再將兩個和相加。如果用S(n)表示由n的倍數構成的數列元素之和的話,那麼前面的分析就可以寫成S = S(3) + S(5)
同時我們會發現兩個數列有重疊,因為3的倍數的數列和5的倍數的數列必然重疊上15的倍數的數列,也就是說 15,30, 45... 會被加兩遍。
那麼我們在S中減去被重複累加的就可以了,所以最終公式可以寫成 S = S(3) + S(5) - S(15)
此時,其實我們在草稿紙上就能得出答案了,但如要寫成代碼的話,參考下面:
參考代碼
#include <stdio.h>int s(int a1, int d, int max){int N = max/d;int an = a1 + (N-1)*d;return (a1+an)*N/2;}int main(){int n = 999; //1000-1int i;i = s(3, 3, n) + s(5, 5, n) - s(15, 15, n);printf("%d\n",i); return 0;
}
不要寫成下面的代碼,那有點沒動腦筋和浪費電腦資源的表現
int test(int n){int i;int sum = 0; for(i=1; i<=n; i++){ if(i%3==0 || i%5==0) { sum += i; }}
return sum;}
擴充:
提一個可以採用相同解法的題目: 從元年開始到第N年(比如1998)時共經過了多少天?
註:當完成題目後,對於某些題,官方網站會給出參考答案,在我的部落格裡不會將官方答案貼出來,僅僅會寫下我自己當時的思路,除非兩者不謀而合。另外,如果你有更好的思路,請留言告訴我,我非常樂意參與到討論中來。