Codewars进阶之路——Factorial tail

题意大概是输入两个数m,n,分别表示进制数(≤256)和底数(≤1000000),求n的阶乘在m进制的表示下最后有几个0
最容易想到的方法如下:

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++;

后面都是一样的,但是反而出错了,不知道是什么原因,还望各位不吝告知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值