Codewars进阶之路——Factorial tail
2017-03-19 21:26
162 查看
题意大概是输入两个数m,n,分别表示进制数(≤256)和底数(≤1000000),求n的阶乘在m进制的表示下最后有几个0
最容易想到的方法如下:
但是很明显一旦number大起来,很容易超出int的表示范围
因此这里就想到另一种方法,思路大致如下:
例如要算10进制下阶乘的结果末尾有几个0,以12为例:
首先,10有素因子2和5,且权值各为1
然后遍历一遍阶乘的每个数,即2~12,针对每个数看看是否能被2或5整除,若能被整除,则记录下整除的次数,如2能被2整除1次,则2对应的记录+1,4能被2整除2次,则2对应的记录+2,5能被5整除1次,则5对应的记录+1,直至遍历结束
最后,将每个素因子被对应的记录做除运算,如这里12的阶乘中,2理论上被记录了10次,5被记录了2次,而2和5的权值都是1,所以最后的结果分别是2和10,取其较小值2,即为最后0的个数
再说16进制也是类似,此时2的权值为4,最后计算n个数中能被2整除的次数,除以4取整即为结果
这里贴出我的代码:
然后这里出现了另一个问题,因为我的原意是先打个素数表,这样效率应该会高一点,但是一不小心那个素数表没用到,直接就pass了,后来加上了素数表的内容后前一部分代码变为如下内容:
后面都是一样的,但是反而出错了,不知道是什么原因,还望各位不吝告知。
最容易想到的方法如下:
int Zeroes (int base, int number) { int f; for (f = 1; number > 1; f *= number--); int z = 0; while (f % base == 0) { f /= base; z++; } return z; }
但是很明显一旦number大起来,很容易超出int的表示范围
因此这里就想到另一种方法,思路大致如下:
例如要算10进制下阶乘的结果末尾有几个0,以12为例:
首先,10有素因子2和5,且权值各为1
然后遍历一遍阶乘的每个数,即2~12,针对每个数看看是否能被2或5整除,若能被整除,则记录下整除的次数,如2能被2整除1次,则2对应的记录+1,4能被2整除2次,则2对应的记录+2,5能被5整除1次,则5对应的记录+1,直至遍历结束
最后,将每个素因子被对应的记录做除运算,如这里12的阶乘中,2理论上被记录了10次,5被记录了2次,而2和5的权值都是1,所以最后的结果分别是2和10,取其较小值2,即为最后0的个数
再说16进制也是类似,此时2的权值为4,最后计算n个数中能被2整除的次数,除以4取整即为结果
这里贴出我的代码:
#include <bitset> #include <map> #include <cmath> std::bitset<1000001> num; void init(int n) { for (int i = 2; i <= std::sqrt(n*1.0)+1; ++i) { if (num[i] == 0) { for (int j = i*i; j <= n; j += i) num[j] = 1; } } } int Zeroes(int base, int number) { init(number); std::map<int, int> mp, op; while (base != 1) { for (int i = 2; i <= base; ++i) if (base%i == 0) { base /= i; mp[i]++; break; } } for (int i = 2; i <= number; ++i) { std::map<int, int>::iterator it; int tmp = i; while (tmp != 1) { for (it = mp.begin(); it != mp.end(); ++it) { int num = it->first; if (tmp%num == 0) { op[num]++; tmp /= num; break; } } if (it == mp.end()) break; } } int MIN = 1e10; std::map<int, int>::iterator it = mp.begin(); for (; it != mp.end(); ++it) { int tmp = it->first; int res = op[tmp] / mp[tmp]; if (res < MIN) MIN = res; } return MIN; }
然后这里出现了另一个问题,因为我的原意是先打个素数表,这样效率应该会高一点,但是一不小心那个素数表没用到,直接就pass了,后来加上了素数表的内容后前一部分代码变为如下内容:
int nm[1000001]; void init(int n) { bitset<1000001> num; for (int i = 2; i <= sqrt(n*1.0)+1; ++i) { if (num[i] == 0) { for (int j = i*i; j <= n; j += i) num[j] = 1; } } int pos = 0; for (int i = 2; i <= n; ++i) if (num[i] == 0) nm[pos++] = i; } int Zeroes(int base, int number) { init(number); map<int, int> mp, op; int temp = number; for (int i = 0; nm[i] <= temp;) if (temp%nm[i] == 0) { mp[nm[i]]++; temp /= nm[i]; } else i++;
后面都是一样的,但是反而出错了,不知道是什么原因,还望各位不吝告知。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- c++指针使用形参改变实参的方法
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析