S=a + (a + 1) + (a + 2) + ...... + b(其中a, b > 0)
現在我們要求,給定一個正整數S,求有多少種不同的<a,b>,使得上述的等式成立。
這個問題很有意思,我猜大家一定想出了比較簡單的那個方法了。
方法1:
程式碼大概是這個樣子的:
int sum = 0; for(int st = 1, ed = 1; ed < S/2;){ if(sum < S){ sum += ed; ed++; } else if(sum == S) { printf("Find a solution: %d %d\n", st, ed); sum += ed; ed++; } else { sum -= st; st++; } }
這段程式碼的意思就是利用兩個遊標進行不斷的逼近,終會找到所有的答案。
雖然這種方法簡單,但是如果我們手邊恰好沒有電腦,我們應該怎麼算?我們如何用筆算出答案呢?試試S=100。
前天看具體數學,偶然找到了一個非常棒的方法,這個方法怎麼就沒想到呢?
方法2:
那個方法大概是這個樣子:
S=a + (a + 1) + (a + 2) + ...... + b = 1/2 * (a+b)(b-a+1)
2S=(a+b)(b-a+1)=xy
令 x=a+b,y=b-a+1,求得 a=(x-y+1)/2, b = (x+y-1)/2。
因為a,b肯定都是整數,所以有如下結論:x,y奇偶性互反,也就是說,若x是奇數,則y為偶數,若x為偶數,y則為奇數,否則a,b將不會是整數(能想明白麼?)。
那麼得到了這些資訊又有什麼用呢?有用,好戲來了。
由上面的結論可知,每一個x,y(滿足x,y奇偶性不同)都會得到一個(a,b)對,所以不同的a,b的數目與2S的因子數有關係。那麼接下來我們就要找出所有滿足條件的x,y。
這個問題又回到了一個老生常談的整數的質因子分解問題上了。
詳情可參考另一篇部落格(開燈關燈問題),具體內容這裡就不贅述了。下面直接來進行計算。
對2S進行質因數分解得:
2S=2^e[1]*p[2]^e[2]*......*p[m]^e[m]
那麼,符合條件的x,y數目就是(e[2]+1)*(e[3]+1)*......*(e[m]+1),這裡面沒有用到e[1]是因為x,y其中一個是偶數,只要p[2]^e[2]*......*p[m]^e[m]的每個因子與2^e[1]相乘就會得到一個x,y。
接下來舉個例子來說一下上面方法的過程吧!
S = 10
2S = 20 = (2^2)*5,所以滿足S=a + (a + 1) + (a + 2) + ...... + b的a,b有兩組。因為a,b都大於0,所以x>y。
1: x = 5, y = 4 => a = 1 b = 4 即10=1+2+3+4
2: x = 20, y = 1 => a = 10 b= 10. 即10=10
S=15
2S=30=2*3*5,所以滿足S=a + (a + 1) + (a + 2) + ...... + b的a,b有4組。
1: x=6, y = 5 => a=1,b=5 即15=1+2+3+4+5
2: x=10,y = 3 => a=4,b=6 即15=4+5+6
3: x=15,y = 2 => a=7,b=8 即15=7+8
4: x=30,y = 1 => a=15,b=15 即15=15
到現在為止,我們都限定x>y,這是由a,b>0推出來的,x-y=(a+b)-(b-a+1)=2a-1>0 => x > y。
假如我們不限制a,b必須都取正數會是神馬樣子的結果呢?那麼很容易,只要調換x,y就會得到不一樣的答案。
再拿S=10為例:
1: x = 4, y = 5 => a=0,b=4 即10=0+1+2+3+4
2: x = 1, y = 20 => a=-9,b=10 即10=-9-8-7-......-1-0+1+2+3+......+9+10。
我想大家也看出規律來了,那麼當S=15時,我們也很容易寫出剩下的四種答案:
1: 15=0+1+2+3+4+5
2: 15=-1-2-3+0+1+2+3+4+5+6
3: 15=-6-5-4-3-2-1+0+1+2+3+4+5+6+7+8
4: 15=-14-13-......+0+1+2+......+14+15。
很簡單的質因數分解能解決各種奇妙有趣的問題,真的很有意思。