(一) 此題爲求表達式1+2+3^3+4+5+6^3+……的值,給定的n可能不是3的倍數。
(二) 此題若採用公式化簡的方法:
設n是3的倍數:1+2+3^3+4+5+6^3+……+n^3
=(1+2+3+..+n)-(3+6+9+..+n)+27*(1^3+2^3+3^3+..+[n/3]^3)
=n*(n+1)/2-n*(n+3)/6+27*[n/3(n/3+1)/2]^2
若化簡到最後爲: n*n*(n^2+6*n+2) /12;
(三) 代碼設計過程:
若採用直接利用最簡公式n*n*(n^2+6*n+2) /12,是錯誤的。
很容易理解公式從左到右乘法得n的最高次方爲4,而n最大爲6位,乘起來必然超過了__int64d的表示範圍。
比如n=90000時,得到結果-681050182461517205,說明有溢出。
#include<stdio.h>
int main()
{
__int64 n,temp,sum;
while(scanf("%I64d",&n)!=EOF)
{
if(n<0) break;
temp=0;
if(n%3==1) {temp=n;n--;}
else if(n%3==2) {temp=2*n-1;n-=2;}
//使n是3的倍數
sum=n*n*(n*n+6*n+13)/12;
printf("%I64d\n",sum+temp);
}
return 1;
}
解決方法:採用倒數第二步公式n*(n+1)/2-n*(n+3)/6+27*[n/3(n/3+1)/2]^2,求sum。
sum=n/3*(n/3+1)/2;
sum*=sum;
sum=sum*27+n*(n+1)/2-n*(n+3)/6;
這樣就可以了!!
(四)另一種解法,最基本的遞歸。
此題目用遞歸反而比直接利用公式略少用時間,可能是公式中乘法的時間超過了遞歸的加法運行時間吧。
#include<stdio.h>
// if i can be divided exactly by 3 sum(i) = sum(i-1) + i*i*i;else sum(i) = sum(i-1) + i;
__int64 sum[100001];
int main()
{ __int64 i,n;
sum[0]=0;
for(i=1;i<=100000;i++)
{if(i%3==0) sum[i]=sum[i-1]+i*i*i;
else sum[i]=sum[i-1]+i;
}
while(1)
{scanf("%I64d",&n);
if(n<0) break;
printf("%I64d\n",sum[n]);
}
return 1;
}
(五) 總結:
當遇到求解公式,而公式中有n^4等等,n又比較大時,不要直接求,採用分佈就可以了