nyoj 954
N!
時(shí)間限制:1000?ms ?|? 內(nèi)存限制:65535?KB 難度:3 描述階乘(Factorial)是一個(gè)很有意思的函數(shù),但是不少人都比較怕它。現(xiàn)在這里有一個(gè)問(wèn)題,給定一個(gè)N(0<0<1000000000),求N!的二進(jìn)制表示最低位的1的位置(從右向左數(shù))。
輸入3! = (6)10 = (110)2,則第一個(gè)1是第二位
4! = (24)10 = (11000)2,則第一個(gè)1是第四位
解題思路:
在做這個(gè)題目之前,先來(lái)看一個(gè)問(wèn)題:
給定一個(gè)整數(shù)N,那么N的階乘N!末尾有多少個(gè)0呢?例如:N=10,N!=362800,N!的末尾有兩個(gè)0;
?首先,最直接的算法當(dāng)然是直接求出來(lái)N!然后看末尾有幾個(gè)0就行了。但這里存在兩個(gè)問(wèn)題:
???? (1)不管使用long或者double一定會(huì)產(chǎn)生溢出。
???? (2)效率低下。
????? 對(duì)于問(wèn)題(1),我們可以采用字符串存儲(chǔ)的辦法解決,但問(wèn)題(2)是由本身算法決定的,所以只能采用其他的算法。
那 到底有沒(méi)有更好的算法呢?我們來(lái)分析,N!能產(chǎn)生0的質(zhì)數(shù)組合只能是2 * 5,也就是說(shuō)當(dāng)對(duì)N!進(jìn)行質(zhì)數(shù)分解之后,N!末尾0的個(gè)位M取決于2的個(gè)數(shù)X和5的個(gè)數(shù)Y的最小值,即M = min(X,Y)。又因?yàn)槟鼙?整除的數(shù)出現(xiàn)的頻率比能被5整除的數(shù)高得多,且出現(xiàn)一個(gè)5的時(shí),最少會(huì)同時(shí)出現(xiàn)一個(gè)2,所以M = Y。即得出Y的值就可以得到N!末尾0的個(gè)數(shù)。
計(jì)算Y,最直接的方法,就是計(jì)算機(jī)1…N的因式分解中5的個(gè)數(shù),然后求和。
那 么還有沒(méi)有更簡(jiǎn)單點(diǎn)的方法呢?我們想,Y還能怎么樣得到?舉個(gè)例子 25的階乘中,總共有6個(gè)五,其中5,10,15,20,各貢獻(xiàn)一個(gè),25貢獻(xiàn)兩個(gè),也可以說(shuō)成,5,10,15,20,25各貢獻(xiàn)一個(gè),25又額外貢獻(xiàn) 一個(gè),即5的倍數(shù)各貢獻(xiàn)一個(gè)5,25的倍數(shù)各貢獻(xiàn)一個(gè)5,即Y=[25/5] + [25/25]。同理,125中,5的倍數(shù)各貢獻(xiàn)一個(gè)5,25的倍數(shù)各貢獻(xiàn)一個(gè)5,125的倍數(shù)也各貢獻(xiàn)一個(gè)5,所以Y=[125/5] + [125/25] + [125/125],所以可得公式:
Y = [N/5] + [N/52] + [N/53] + …
代碼如下:long GetZeroNum(long n) {long num = 0;while(n != 0){num=num+n/5;n=n/5;}return num; }
回到這個(gè)題目上,這個(gè)題目問(wèn)的是二進(jìn)制中,最低位1的位置。那么最低位1之后的肯定全為0,現(xiàn)在就是要找到末尾有多少個(gè)0。那么我們的想法和上面一樣,找有多少個(gè)2的倍數(shù)。
AC:
#include<iostream> using namespace std;typedef long long LL;int main() { LL n,sum;while(cin>>n) {sum = 0;while(n){sum += n/2;n /= 2;}cout<<sum+1<<endl;}return 0; }
總結(jié)
- 上一篇: nyoj 998(欧拉定理的运用)
- 下一篇: 【JEECG技术文档】表单配置-树形表单