一个ACM问题

网上有朋友求下面 ACM 题目的翻译:

Problem Description
In many applications very large integers numbers are required. Some of these applications are using keys for secure transmission of data, encryption, etc. In this problem you are given a number, you have to determine the number of digits in the factorial of the number.

Input
Input consists of several lines of integer numbers. The first line contains an integer n, which is the number of cases to be tested, followed by n lines, one integer 1 ≤ n ≤ 107 on each line.

Output
The output contains the number of digits in the factorial of the integers appearing in the input.

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

玄机逸士翻译如下:

问题描述
在很多应用中,都需要用到很大的整数。其中有些应用用密钥来保证数据传输的安全、加密等。在这个问题中,给你一个数字,请计算出该数字的阶乘的位数。

输入
输入有几行整数数字组成。第一行包含一个整数 n ,代表有多少种需要测试的情况,随后是 n 行数字,这些数字均为大于等于 1 和小于等于 107 的整数。

输出
输出包含输入中出现的整数的阶乘的位数。

 

译者注释:

问题描述的第一句话和这个问题的解答本身并没有很大的关系,但说出了大整数和加解密是有很大关系的事实。著名的非对称加解密算法 RSA 中,就需要用到一个很大的素数。 这个题目在解题的时候,千万不要被前面的话牵制住注意力,如果你知道上面说的背景知识,应该就可以避免注意力被 deviated 了。当然比赛估计是要考Sterling公式,咱们这里不是比赛,不去管它。

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

解题思路如下:

#include <iostream>

#include <math.h>

using namespace std;

// 计算数字 n 的阶乘有多少位

int factorialdigits(int n)

{

         double doubledigits = 0.0;

         for(int i = 1; i <=n; i++)

         {

                   doubledigits += log10(i);

         }

         return ceil(doubledigits);

}

 

int main()

{

         int n = 107;

         cout << factorialdigits(n) << endl;

   

    return 0;

}

作为例子,当 107 的阶乘最后所得数字的位数为 173 !很大的数字了。

 

需要说明的是, ceil(log10(10)) = 1 ,照此解释 10 的位数是 1 ,这显然不对,但可以肯定这样的情况在 factorialdigits 中,不可能碰到。另外一个更好好的办法就是将 ceil(doubledigits) 改为 floor(doubledigits) + 1 ,这样就不存在任何问题了。

 

有了上面的思路,这个题目就不难解了。下面是最后的代码:

#include <iostream>

#include <math.h>

using namespace std;

int factorialdigits(int n)

{

         double doubledigits = 0.0;

         for(int i = 1; i <=n; i++)

         {

                   doubledigits += log10(i);

         }

         return floor(doubledigits) + 1;

}

 

int main()

{

         int i = 0;

         int k = 0;

         int x = 0;

         int a[108];

         cin >> k;

         if(k < 1 || k > 107) // 判断输入的数字是否在[1, 107]之间,如果不在,直接退出程序。

         {

                   cout << "The entered number should be in the range of [1, 107], please retry." << endl;

                   return 0;

         }

         else

         {

                   a[0] = k;      // 将下面需要输入的数字个数,存放在a[0]中

                   for(i = 1; i <= k; i++)   // 准备接受k个数字

                   {

                            cin >> x;  

                            if(x < 1 || x > 107)    // 提出输入的数字不在[1, 107]内的情况,并继续接受数据

                            {

                                     cout << "The entered number should be in the range of [1, 107], please retry." << endl;

                                     if(i > 0) i--;

                                     continue;

                            }

                            else

                            {       

                                     a[i] = x;

                            }

                   }

         }

 

         // 输出所输入数字的阶乘的位数

         for(i = 1; i <= k; i++)

         {

                   cout << "The digits of factorial of " << a[i] << " is " << factorialdigits(a[i]) << endl;

         }

   

    return 0;

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值