欢迎使用CSDN-markdown编辑器
2015-07-22 22:48
218 查看
本篇文章的基础请 先看这里
先将N中5的倍数用1代替,然后每10个分成一组,也许你要问10个一组怎么看出来的?因为只求最后一位,而每10个最后的尾数相同,一开始也没有想到,参考网上的例子才想到,这样就分成了N/10 这里的除法是整除,那么在不算上5的倍数的基础上得到
1. X
= data
当N < 10
2. X
= data[N%10] * 6 当N >= 10
X
即代表尾数
data[10] ={1, 1, 2, 6, 4, 4, 4, 8, 4, 6};
data分别为0到9的阶乘最后一个不为0的位,将5的倍数的地方用1代替。
X
= data[N%10] * 6 当N >= 10
为什么要乘以6 其实准确的来讲不是乘以6而是 6^(N/10)但是6*6 最后一位还是6 所以可以写成乘以6
还有一个就是只要N>1以后都是偶数,而偶数的结尾是一定是2,4,6,8 为什么没有0 因为5的倍数,都被剔除了,而6乘以2,4,6,8之后还是2,4,6,8.
也就是说,N>2之后,我可以在总的后面乘以6对结果没有影响
然后再来看5的倍数那一部分,它们是:5*10 * 15 * 20 * 25 * 30 * 35
我们发现将他们提取公因子,可以写成 5^P * P!。其中P = [N/5],因为求得是阶乘最后一位非零位,所以这里的5^P必须要用P个2来匹配掉,如果将最后的非零位记为T
的话,那么T
= (X
/ 2^P) * T[P]; 这里的除法不是不同意义的除法,因为X
有可能是1位数,我们发现:
2^1 % 10 = 2,
2^2 % 10 = 4,
2^3 % 10 = 8,
2^4 % 10 = 6,
每四个一循环,当P == 0的时候比较特殊,2^P % 10 = 1
除上2^P其实就是乘上2^(-P),这样处理就简单了,根据循环的性质就可以将T
简化成T
= X
* 2^(-P) * T[P],这样一来,算法的复杂度就只有O(log5(N))了。并且2是每四个一循环,2^(-P) = 2^(-P % 4 + 4)。 计算T
只需要递归计算T[N/5]即可。
那么
0 - 4 的时候要除以 2^0 = 1
5 - 9 的时候要除以 2^1 = 2
10 - 14 的时候要除以 2^2 = 4
15 - 19 的时候要除以 2^3 = 8
20 - 24 的时候要除以 2^4 = 6
又因为我说过乘以6没有影响 所以我在20-24的时候乘以一个6 那么就相当于20-24的时候我乘以一个6再除以一个6 等于除以一个1
那么此时就循环了 一个的循环节是4 一个循环节是10 所以循环节为20
先将N中5的倍数用1代替,然后每10个分成一组,也许你要问10个一组怎么看出来的?因为只求最后一位,而每10个最后的尾数相同,一开始也没有想到,参考网上的例子才想到,这样就分成了N/10 这里的除法是整除,那么在不算上5的倍数的基础上得到
1. X
= data
当N < 10
2. X
= data[N%10] * 6 当N >= 10
X
即代表尾数
data[10] ={1, 1, 2, 6, 4, 4, 4, 8, 4, 6};
data分别为0到9的阶乘最后一个不为0的位,将5的倍数的地方用1代替。
X
= data[N%10] * 6 当N >= 10
为什么要乘以6 其实准确的来讲不是乘以6而是 6^(N/10)但是6*6 最后一位还是6 所以可以写成乘以6
还有一个就是只要N>1以后都是偶数,而偶数的结尾是一定是2,4,6,8 为什么没有0 因为5的倍数,都被剔除了,而6乘以2,4,6,8之后还是2,4,6,8.
也就是说,N>2之后,我可以在总的后面乘以6对结果没有影响
然后再来看5的倍数那一部分,它们是:5*10 * 15 * 20 * 25 * 30 * 35
我们发现将他们提取公因子,可以写成 5^P * P!。其中P = [N/5],因为求得是阶乘最后一位非零位,所以这里的5^P必须要用P个2来匹配掉,如果将最后的非零位记为T
的话,那么T
= (X
/ 2^P) * T[P]; 这里的除法不是不同意义的除法,因为X
有可能是1位数,我们发现:
2^1 % 10 = 2,
2^2 % 10 = 4,
2^3 % 10 = 8,
2^4 % 10 = 6,
每四个一循环,当P == 0的时候比较特殊,2^P % 10 = 1
除上2^P其实就是乘上2^(-P),这样处理就简单了,根据循环的性质就可以将T
简化成T
= X
* 2^(-P) * T[P],这样一来,算法的复杂度就只有O(log5(N))了。并且2是每四个一循环,2^(-P) = 2^(-P % 4 + 4)。 计算T
只需要递归计算T[N/5]即可。
那么
0 - 4 的时候要除以 2^0 = 1
5 - 9 的时候要除以 2^1 = 2
10 - 14 的时候要除以 2^2 = 4
15 - 19 的时候要除以 2^3 = 8
20 - 24 的时候要除以 2^4 = 6
又因为我说过乘以6没有影响 所以我在20-24的时候乘以一个6 那么就相当于20-24的时候我乘以一个6再除以一个6 等于除以一个1
那么此时就循环了 一个的循环节是4 一个循环节是10 所以循环节为20
相关文章推荐
- 分布式存储
- tomcat安装
- 算法正确性
- UI5 如何修改默认的style
- 股票学习(K线分析)
- 探索MySQL高可用架构之MHA(1)
- 在html 中,将中文转换为 html实体再输出 即: &#开头的html实体编码
- VC++中"using namespace std"有什么用的
- Jenkins安装与配置
- 利用struts实现jsp中的图片上传和预览
- [leetcode] Product of Array Except Self
- 带限制求最小价值的完全背包 HDU1114
- [leedcode 120] Triangle
- 顶级操盘手是怎样准确把握入场时机的
- Coding 代码管理快速入门(转)
- epoll源码实现分析
- Linux kernel 分析之十三:kbuild系统-编译到内核和编译成模块的区别
- try语句的基本用法
- swt
- 使用nohup在后台运行scp