【问题标题】:Trailing zeroes in a Factorial阶乘中的尾随零
【发布时间】:2014-09-10 11:43:02
【问题描述】:

我正在尝试编写一个代码来计算特定数字(大数)的阶乘中尾随零的数量。但是,对于小数字,我得到了正确的结果,但对于大数字,偏差不断增加。我的逻辑有什么问题

#include <stdio.h>

int main(void) {
    int t;

    scanf("%d", &t);
    while (t > 0) {
        int factorten = 0, factorfive = 0, factortwo = 0, remainingfive = 0,
            remainingtwo = 0;
        unsigned int factors = 0;
        unsigned int n;
        scanf("%u", &n);
        for (unsigned int i = n; i > 0; i--) {
            if (i % 10 == 0) {
                factorten++;
                continue;
            } else if (i % 5 == 0) {
                factorfive++;
                continue;
            } else if (i % 2 == 0) {
                // int new = i;
                // while(new % 2 == 0)
                //{
                // new = new / 2;
                factortwo++;
                //}
                continue;
            }
        }

        factors = factors + factorten;
        printf("%u\n", factors);
        if (factorfive % 2 == 0 && factorfive != 0) {
            factors = factors + (factorfive / 2);
        } else {
            remainingfive = factorfive % 2;
            factors = factors + ((factorfive - remainingfive) / 2);
        }
        printf("%u\n", factors);
        if (factortwo % 5 == 0 && factortwo != 0) {
            factors = factors + (factortwo / 5);
        } else {
            remainingtwo = factortwo % 5;
            factors = factors + ((factortwo - remainingtwo) / 5);
        }
        printf("%u\n", factors);
        if ((remainingfive * remainingtwo % 10) == 0 &&
            (remainingfive * remainingtwo % 10) != 0) {
            factors++;
        }
        printf("%u\n", factors);
        t--;
    }
}

示例输入:

6
3
60
100
1024
23456
8735373

样本输出:

0
14
24
253
5861
2183837

我的输出

0
13
23
235
5394
2009134

【问题讨论】:

  • 出了什么问题?
  • 对于最多 3 位数字,我的结果比实际值少 1,并且从那里它会出现很大程度的错误
  • 另外,您需要计算重复因素。 4 应该对 factortwo 贡献两个,而不仅仅是一个。您有(注释掉)代码来执行此操作,但您也需要 5 和 10 的类似代码。
  • 三位数表示你得到 100,即 10*10,所以需要数 2 才能分解
  • 代码太糟糕了。

标签: c


【解决方案1】:

编辑:忽略前两个,它们不是最理想的。第三种算法是最优的。

我认为这可以满足您的要求,但更简单且有效:

int tzif(int n)
{
    int f2 = 0, f5 = 0;
    for (;n > 1; n--)
    {
        int x = n;
        for (;x % 2 == 0; x /= 2)
            f2++;
        for (;x % 5 == 0; x /= 5)
            f5++;
    }
    return f2 > f5 ? f5 : f2;
}

它计算数字 N...2 的 2 因子和 5 因子。然后它返回两者中较小的一个(因为如果不添加 5 因子,添加 2 因子是没有用的,反之亦然)。你的代码太奇怪了,我无法分析。

我认为这也应该有效,因为阶乘将有足够的 2 因子来“覆盖”5 因子:

int tzif(int n)
{
    int f5 = 0;
    for (;n > 1; n--)
        for (x = n;x % 5 == 0; x /= 5)
            f5++;

    return f5;
}

这仅计算 5 因子并返回。

我认为应该可行的另一种方法:

int tzif(int n)
{
    int f5 = 0;
    for (int d = 5; d <= n; d *= 5)
        f5 += n / d;

    return f5;
}

每五个数字计数一次(每个数字都有一个 5 因子),然后每 25 个数字计数一次(每个数字都有另一个 5 因子),等等。

【讨论】:

  • 超过时间限制,需要更高效的
  • 问题不在于 svinja 的代码。为了有效地处理许多测试用例,您需要在测试用例之间重用数据。
  • 好的,我修复了最后一个错误,现在它应该是正确的并且在对数时间内运行。
【解决方案2】:

有 3 个计数器 - c2,c5,c10。

我认为支票应该是

  1. 能被 5 整除但不能被 10 整除 -> c5++
  2. 能被 2 整除但不能被 10 整除 -> c2++
  3. 可被 10 整除。此处如果为真,则计算 0 的个数。 (c10++)

最后一个 0 将是

smaller_of(c2,c5) + c10

尝试使用它来编写代码。应该可以。

【讨论】:

  • 没有必要考虑 10,因为它们也可以被 5 和 2 整除。此外,您需要任何检查重复除以 2(或 5),因为(比如说)25 有贡献5 的两个因数。
【解决方案3】:

首先N! 中的trailing 02 and 5 (10) 因素决定。在这种情况下,factors 2 总是比factors 5 更多,您只需计算factors 5N! 中的位置。

(N!/5) 会给你 5 的倍数 (5^1)N!
(N!/25) 会给你25 的倍数 ( N!
(N!/125) 中的 5^2)
将在 N!
... 中为您提供 125 的倍数 (5^3)
br>(N!/5^n) 会在N! 中为您提供5^n 的倍数

当您添加multiple of 5 时,您也添加了25, 125, ..., 5^n 的倍数,当您添加multiple of 25 时,您也添加了125, ..., 5^n 的倍数,等等...

在这种情况下,您只需要迭代小于或等于 Npower of 5 并添加该 5 次方的倍数。

代码:

long long trailing_zeros(long long N) {
    long long zeros = 0;
    for (long long power5 = 5; power5 <= N; power5 *= 5)
        zeros += N / power5;
    return zeros;
}

【讨论】:

    【解决方案4】:
    #include<iostream>
    
    int main()
    {
    
        int size,i;
    
        std::cin >> size;
        int*fact;
        fact = new int[size];
        for (i = 0; i < size; i++)
        {
            std::cin >> fact[size];
    
        }
    
        for (i = 0; i < size; i++)
        { 
    
            int con = 5;
            int multiple = 0;
    
    
            do
            {
                multiple = multiple+(fact[size] / con);
                con = con * 5;
    
            } while (con < fact[size]);
            std::cout << multiple <<'\n';
    
    
        }
        return 0;
    }
    

    此代码非常适合单个输入..bt 对于多个输入,它会打印最后输入的数字的 o/p...出了什么问题..我想不通

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2012-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多