生活随笔
收集整理的這篇文章主要介紹了
回《笔试常见的“阶乘”编程题,你写对了么?》
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原帖鏈接:http://www.cnblogs.com/kym/archive/2009/10/05/1578224.html????
????我機器上沒有C#的開發環境,所以沒法測試作者這個代碼的耗時,不過10000的階乘在5秒內完成,不知道作者的代碼是否能達到?我想起前段時間在HDU做的一道ACM題,題目的時限要求是1秒內能計算10000的階乘(當然這是代碼跑在它的服務器的時間)。
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1042
????? 如果按照飛林沙文章中那種常規的思路,逐位相乘,再對齊相加,缺點很明顯,如果n值比較大,運算次數將非常多,必定會超時,1萬的階乘想在1秒內完成肯定無法達成。
??? 我的思路是把數據分組,每組上限為9999,最多可容納2萬組,每組4位整數,則可以容納8萬位整數(當然,組數可以隨你要計算的n的大小進行調整),利用組與組的錯位相乘再相加,可以避免樓主這樣逐位進行運算。
代碼如下:
#include<iostream>?#include<stdio.h>?#include<string>?#include<iomanip>?#include<algorithm>?using?namespace?std; ?#include?"time.h" ??const?int?MAX_GROUPS?=?20000;//最多2萬組,每組最多4位整數,即最多可容納8萬位整數 ?const?int?MAXN?=?9999;//每組的上限值 ?const?int?GROUP_LEN?=?4;//每組的最大長度 ??class?BigInteger ?{ ?private: ?????int?data[MAX_GROUPS]; ?????int?len; ?????void?init() ?????{ ?????????memset(data,0,sizeof(data)); ?????} ?public: ?????BigInteger() ?????{ ?????????init(); ?????????len?=?0; ?????} ?????BigInteger(const?int?b); ?????BigInteger(const?BigInteger?&); ??????bool?operator?>?(const?BigInteger&)const; ?????BigInteger?&?operator=(const?BigInteger?&); ?????BigInteger?&?add(const?BigInteger?&); ?????BigInteger?&?sub(const?BigInteger?&); ?????BigInteger?operator+(const?BigInteger?&)?const; ?????BigInteger?operator-(const?BigInteger?&)?const; ?????BigInteger?operator*(const?BigInteger?&)?const; ?????BigInteger?operator/(const?int?&)?const; ?????void?print(); ?}; ?BigInteger::BigInteger(const?int?num) ?{ ?????int?res,tmp?=?num; ?????len?=?0; ?????init(); ?????while(tmp?>?MAXN) ?????{ ?????????res?=?tmp?-?tmp?/?(MAXN?+?1)?*?(MAXN?+?1); ?????????tmptmp?=?tmp?/?(MAXN?+?1); ?????????data[len++]?=?res; ?????} ?????data[len++]?=?tmp; ?} ?BigInteger::BigInteger(const?BigInteger?&?rhs)?:?len(rhs.len) ?{ ?????int?i; ?????init(); ?????for(i?=?0?;?i?<?len?;?i++) ?????{ ?????????data[i]?=?rhs.data[i]; ?????} ?} ?bool?BigInteger::operator?>?(const?BigInteger?&rhs)const ?{ ?????int?ln; ?????if(len?>?rhs.len) ?????{ ?????????return?true; ?????} ?????else?if(len?<?rhs.len) ?????{ ?????????return?false; ?????} ?????else?if(len?==?rhs.len) ?????{ ?????????ln?=?len?-?1; ?????????while(data[ln]?==?rhs.data[ln]?&&?ln?>=?0)? ?????????{ ?????????????ln--; ?????????} ?????????if(ln?>=?0?&&?data[ln]?>?rhs.data[ln])? ?????????{ ?????????????return?true; ?????????} ?????????else? ?????????{ ?????????????return?false; ?????????} ?????} ??} ??BigInteger?&?BigInteger::operator?=?(const?BigInteger?&rhs) ?{ ?????init(); ?????len?=?rhs.len; ?????for(int?i?=?0?;?i?<?len?;?i++) ?????{ ?????????data[i]?=?rhs.data[i]; ?????} ?????return?*this; ?} ?BigInteger&?BigInteger::add(const?BigInteger?&rhs) ?{ ?????int?i,nLen; ??????nLen?=?rhs.len?>?len???rhs.len?:?len; ?????for(i?=?0?;?i?<?nLen?;?i++) ?????{ ?????????data[i]?=?data[i]?+?rhs.data[i]; ?????????if(data[i]?>?MAXN) ?????????{ ?????????????data[i?+?1]++; ?????????????data[i]?=?data[i]?-?MAXN?-?1; ?????????} ?????} ?????if(data[nLen]?!=?0)? ?????{ ?????????len?=?nLen?+?1; ?????} ?????else? ?????{ ?????????len?=?nLen; ?????} ??????return?*this; ?} ?BigInteger?&?BigInteger::sub(const?BigInteger?&rhs) ?{ ?????int?i,j,nLen; ?????if?(len?>?rhs.len) ?????{ ?????????for(i?=?0?;?i?<?nLen?;?i++) ?????????{ ?????????????if(data[i]?<?rhs.data[i]) ?????????????{ ?????????????????j?=?i?+?1; ?????????????????while(data[j]?==?0)?j++; ?????????????????data[j]--; ?????????????????--j; ?????????????????while(j?>?i) ?????????????????{ ?????????????????????data[j]?+=?MAXN; ?????????????????????--j; ?????????????????} ?????????????????data[i]?=?data[i]?+?MAXN?+?1?-?rhs.data[i]; ?????????????} ?????????????else? ?????????????{ ?????????????????data[i]?-=?rhs.data[i]; ?????????????} ?????????} ?????????len?=?nLen; ?????????while(data[len?-?1]?==?0?&&?len?>?1)? ?????????{ ?????????????--len;???? ?????????} ?????} ?????else?if?(len?==?rhs.len) ?????{ ?????????for(i?=?0?;?i?<?len?;?i++) ?????????{ ?????????????data[i]?-=?rhs.data[i]; ?????????} ?????????while(data[len?-?1]?==?0?&&?len?>?1)? ?????????{ ?????????????--len;???? ?????????} ?????} ?????return?*this; ?} ?BigInteger?BigInteger::operator+(const?BigInteger?&?n)?const? ?{ ?????BigInteger?a?=?*this; ?????a.add(n); ?????return?a; ?} ?BigInteger?BigInteger::operator-(const?BigInteger?&?T)?const ?{ ?????BigInteger?b?=?*this; ?????b.sub(T); ?????return?b; ?} ?BigInteger?BigInteger::operator?*?(const?BigInteger?&rhs)?const ?{ ?????BigInteger?result; ?????int?i,j,up; ?????int?temp,temp1; ??????for(i?=?0;?i?<?len;?i++) ?????{ ?????????up?=?0; ?????????for(j?=?0;?j?<?rhs.len;?j++) ?????????{ ?????????????temp?=?data[i]?*?rhs.data[j]?+?result.data[i?+?j]?+?up; ?????????????if(temp?>?MAXN) ?????????????{ ?????????????????temptemp1?=?temp?-?temp?/?(MAXN?+?1)?*?(MAXN?+?1); ?????????????????up?=?temp?/?(MAXN?+?1); ?????????????????result.data[i?+?j]?=?temp1; ?????????????} ?????????????else? ?????????????{ ?????????????????up?=?0; ?????????????????result.data[i?+?j]?=?temp; ?????????????} ?????????} ?????????if(up?!=?0) ?????????{ ?????????????result.data[i?+?j]?=?up; ?????????} ?????} ?????result.len?=?i?+?j; ?????while(result.data[result.len?-?1]?==?0?&&?result.len?>?1)?result.len--; ?????return?result; ?} ?BigInteger?BigInteger::operator/(const?int?&?b)?const ?{ ?????BigInteger?ret; ?????int?i,down?=?0; ??????for(i?=?len?-?1?;?i?>=?0?;?i--) ?????{ ?????????ret.data[i]?=?(data[i]?+?down?*?(MAXN?+?1))?/?b; ?????????down?=?data[i]?+?down?*?(MAXN?+?1)?-?ret.data[i]?*?b; ?????} ?????ret.len?=?len; ?????while(ret.data[ret.len?-?1]?==?0)?ret.len--; ?????return?ret; ?} ?void?BigInteger::print() ?{ ?????int?i; ??????cout?<<?data[len?-?1]; ?????for(i?=?len?-?2?;?i?>=?0?;?i--) ?????{ ?????????cout.width(GROUP_LEN); ?????????cout.fill('0'); ?????????cout?<<?data[i]; ?????} ?????cout?<<?endl; ?} ?int?main() ?{?? ?????clock_t???start,???finish;??? ?????double?????duration;??? ?????int?i,n; ?????BigInteger?result,num; ?????scanf("%d",&n); ?????start???=???clock();???? ?????result?=?BigInteger(1); ?????for(i?=?2;i?<=?n;?++i) ?????{ ?????????num?=?BigInteger(i); ?????????resultresult?=?result?*?num; ?????} ?????result.print(); ?????finish???=???clock();??? ?????duration???=???(double)(finish???-???start)???/???CLOCKS_PER_SEC;?? ?????printf(???"%f???seconds\n",???duration???);??? ?????return?0; ?}? 下面給出測試結果,
我的機器配置:酷睿雙核2.0G,內存3G, ?計算10000的階乘,我的機器用時3.312秒,在HDU的服務器上,10000的階乘用時不到900毫秒。 ?計算12345的階乘,我的機器用時5.078秒。 ?計算20000的階乘,我的機器用時13.656秒。? 用C/C++確實是會快些的,HDU的這道題目對Java程序的時限是5秒內完成1萬的階乘,但c/c++的時限是1秒,由此可以看出。
大家也可以試試在HDU的服務器上提交下你的代碼,看看能否在1秒內通過。
此外,還有2個常見的N!題目,就是N!的尾數0的個數和N!的非零末尾數,有興趣的同學可以自己看看。
轉載于:https://blog.51cto.com/phinecos/368956
總結
以上是生活随笔為你收集整理的回《笔试常见的“阶乘”编程题,你写对了么?》的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。