【问题标题】:Making a factorial program faster?使阶乘程序更快?
【发布时间】:2021-10-31 14:31:20
【问题描述】:

我一直试图将这个提交到一个有编程课程的网站,但法官一直告诉我这个程序执行时间太长:/

问题陈述:

编写一个程序,从标准输入读取一个非负整数n,将n!的十进制数中的十位和个位进行计数,并将结果写入标准输出.在输入的第一行有一个整数D (1≤D≤30),表示要考虑的案例数。对于每个条目的情况。您的程序应该在单独的行上打印两个数字(由一个空格分隔):十进制的n! 的十位和个位。

输入/输出:

Input Output
2
1 0 1
4 2 4
#include <iostream>

using namespace std;

int d,n;

int main()
{
    cin>>d;
    for(int i=0; i<d; i++)
    {
        cin>>n;
        int silnia = 1;
        for(int j=n; j>1; j--)
        {
            silnia=silnia*j;
        }
        if(silnia == 1) cout<<0<<" "<<silnia<<"\n";
        else cout<<(silnia/10)%10<<" "<<silnia%10<<"\n";
    }
    return 0;
}

【问题讨论】:

  • 我想发表评论,但就像我必须弄清楚问题陈述,因为你没有提供一个,你必须弄清楚我的评论是什么:D
  • 无论如何,抛开双关语,请将您的问题陈述放在问题中。这样,我们所有人都会更容易理解,然后我们就能更好地为您提供帮助:)
  • @kesarlingHe-Him “factorial”听起来像是一个明确的问题陈述。
  • @bereal,22 4 的阶乘如何? :)
  • @drescherjm,我想是这样的 :) 必须手动输入 test_cases 的数量不是很烦人吗?我的意思是,为什么这些家伙不能简单地运行程序 test_case 次数? ??????????

标签: c++ optimization factorial


【解决方案1】:

你可以摆脱 inner loop,因为n! == (n - 1)! * n:

  cin >> d;

  int factorial = 1;

  cout << 0 << " " << 1 << "\n";

  for (int i = 1; i < d; ++i) {
    /* we operate with last two disgits: % 100 */
    factorial = (factorial * i) % 100;

    cout << factorial / 10 << " " << factorial % 10 << "\n";
  }

编辑:另一个问题是

  silnia=silnia*j;

线。阶乘增长很快

  13! = 6227020800 > LONG_MAX (2147483647)

这就是为什么我们应该使用模算术:我们保留的不是阶乘本身(可能非常大),而是它的最后两个数字(注意% 100),保证在@ 987654326@范围:

  factorial = (factorial * i) % 100;

甚至(如果i 可以很大)

  factorial = (factorial * (i % 100)) % 100;

【讨论】:

  • 我希望学习阶乘或编程的人不会因为尝试使用内部循环的解决方案而感到难过。这样做既直观又合乎逻辑——只是碰巧效率很低。例如,考虑一下,当被问及“Q 之前是什么字母”时,你们中有多少人必须从头开始在你的脑海中唱 ABC 歌曲。
  • 嗯,OP告诉D是测试用例的数量,所以你可以考虑编辑你的答案。
  • @justANewbie 我认为很明显,Dmitry 并没有试图为编程挑战提供解决方案,而是说明(尽管使用代码)n 之间的关系!和(n-1)!然后操作人员可以使用它来改进他们的方法。这就是“授人以渔,养其一生”之类的道理。
【解决方案2】:

由于只需要 n! 的最后 2 位数字,因此任何 n &gt;= 10** 都将具有 n!00 作为最后 2 位数字。

一个捷径是测试n:这会将问题从O(n) 转移到O(1)

  int factorial = 0;
  if (n < 10) {
    int factorial = 1;
    for(int j=n; j>1; j--)
    {
        factorial *= j;
    }
    factorial %= 100;
  }

或者使用 [0...10) 范围内的 n 查找表删除 for 循环。

---

** 10_or_more!里面有一个2 * 5 * 10 * other factors。所有这些阶乘都以00 结尾。

【讨论】:

  • 您关于任何大于 10 的数字都有一个以 00 结尾的阶乘的说法在这里真的很有帮助。
  • 很好的答案。但是,我不确定这真的是O(1)。运行时间不是恒定的——这需要在没有可变数量的迭代的情况下得出一个解决方案。尽管有任何兴趣的n 的最大值是 9,但我认为这仍然是 O(n)。
  • @3Dave -- O(1) 并不意味着所需的时间永远不会改变;这意味着无论输入有多大,时间都有一个上限。对于此示例,上限是计算 9 所需的时间! -- 没有比这个时间更长的输入值。
  • @PeteBecker 我已经纠正了!感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 2019-10-22
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多