N!最后一位非0位的求法
来源:互联网 发布:刚进入金融行业 知乎 编辑:程序博客网 时间:2024/05/01 20:49
PS:这篇文章是很早以前我在使用博客圆的时候写的,后来换了两次搏客,都把这篇文章拿过来了。
问题是求关于N!的最后一位非0位, 如3!=6,最后一位非0位为6, 5!=120, 最后一位非0位为2.怎么样快速的求出最后一位非0位呢?
最朴素的想法就是先求出N!的结果,再求出结果的最后一位非0位.当N比较小时,是可以承受的,但是当N达到一定规模的时候,时间,空间都不会太理想.这里需要一些技巧.既然是求最后一位非0位,我们就可以先除非所有对结果没有影响的数,如10的倍数.于是先把N!因子分解得到形如2^a*5^b*c.这个时候我们去掉一个b个5因子和b个2因子,最后一位非0位是不变的.(N!中2的因子一定不会比5的因子少).于是我们的要求的结果就变为(2^(a-b)*c)%10.由(a*b)%10=((a%10)*(b%10))%10我们可以得((2^(a-b)%10)*(c%10))%10,由于c不会产生未位为0,故只保留c的最未位即可.于是可将c转化为1,3,7,9因子的相乘得到的结果的最未位(因为1,3,7,9因子相乘不会产生最未非0位,故去掉高位不会对结果产生影响,同时1*n=n可以去掉1的因子).
2,3,7,9因子规律如下:
2^1=2, 2^2=4, 2^3=8, 2^4=16->(6), 2^5=32->(2)
3^0=1, 3^1=3, 3^2=9, 3^3=27->(7), 3^4=81->(1)
7^0=1, 7^1=7, 7^2=49->(9), 7^3=343->(3), 7^4=2401->(1)
9^0=1, 9^1=9, 9^2=81->(1), 9^3=729->(9), 9^4=6561->(1)
它们都是以4为循环周期的.于是我们只要求出2, 5, 3, 7, 9因子的个数即可.
首先我们求2,5因子在N!中的个数.2的因子的每个偶数到少有1个,同时将数列中每个数/2,其中的偶数还有一个2因子.直至n=1或n=0结束.5因子求法相同.代码如下:
- int getFactor25(int n, int f){
- int ret=0;
- while(n>0){
- ret+=n/f;
- n/=f;
- }
- return ret;
- }
3,7,9因子的个数有多少呢?对于1,2,3,4......n-1,n来说,未尾以3,7,9结束的数的个数为n/10+(n%10³f?1:0),(f=3,7, 9).同时我们对于对于奇数数列/5可以得到一个新的数列也有3,7,9因子,对于偶数数列/2也可以得到新的数列也有3,7,9的因子,将所有的3,7,9因子相加即可得到总的3,7,9因子的个数.得到3,7,9因子的个数后,我们可以将其全部转化为因子3的个数.因为9=3*3(3^2), 7=(3*3*3(3^3))%10,设f3, f7, f9为3, 7, 9因子的个数,全部转化为因子3的个数为f3+2*f9+3*f7.
于是我们可以用递归同时求2,3,5,7,9因子的个数,代码如下:
- void getFactor(int n){
- if(n==0)
- return;
- for(int m=n; m>0; m/=5){
- int t=m/10, r=m%10;
- f3+=t+(r>=3);
- f5+=t+(r>=5);
- f7+=t+(r>=7);
- f9+=t+(r>=9);
- }
- f2+=n/2;
- getFactor(n/2);
- }
可用两个数组表示循环:
- int p2[4]={6, 2, 4, 8};
- int p3[4]={1, 3, 9, 7};
故结果为(1):当2, 5因子个数相同时,只与3因子相关,结果为p3[f3%4]%10;(2):当2因子大于5因子时,结果同时与3因子和2因子相关,为(p2[f2%4]*p3[f3%4])%10.
其实通过N!的最未非0位的方法我们可以求排列组合数NPM,C(N,M)的最未非0位,用上面的各因子个数减去下面的各因子个数就是结果的各因子个数.只是此时需要注意的是5的因子可能会比2的因子多.当5的因子比2的因子多时,未位一定为5.其余情况与上面相同.
- N!最后一位非0位的求法
- N^N次方最后一位数字的求法
- 求n!的最后一位非零数
- 求阶乘最后一位非0位
- 求N!的最后一个非0位
- 计算n!的最后一位非零数字的算法
- N!最后一位非零数字,好的算法,
- UVA568求n!的最后一位非零数
- 求N!最后非0位 O(N log N)
- 求n的n次方最后一位
- poj 1150 求n!中最后非0位
- poj 3406:Last digit(求C(n, m)的最后一个非0位)
- 如何计算N!的最后一位非零数字(POJ 1604 Just the Facts)
- poj 1150:The Last Non-zero Digit(求A(n, m)的最后一个非0位)
- n的阶乘最后一个非0的数
- hdu 1066 Last non-zero Digit in N! 数学,求n!最后一位非零数
- 求N的阶乘的最后一位数字
- 1199(阶乘结果的最后一位非零数)
- Struts与Hibernate整合
- IRP概述
- 基于.Net Framework的N层分布式应用开发
- Password / Word lists
- 硬盘零磁道损坏的修复方法
- N!最后一位非0位的求法
- 文字列转换成数字形式
- Spring学习笔记:spring集成hibernate
- 几个移位的小例子
- The C10K problem翻译
- windows 2003,windows 7,windows xp 混装方法
- Effective C++学习3 条款03:尽可能使用const
- 开通博客!
- [转贴]怎样让一个Service开机自动启动