(int)log10((int)n)+1 计算位数的几个问题

本文介绍了一种计算大数阶乘位数的方法,利用对数特性与斯特林公式,解决了传统方法在处理大数据时的效率问题。通过两种不同算法实现并对比了其在不同平台上的运行效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Big Number

Time Limit: 20000/10000 MS (Java/Others)     Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2768     Accepted Submission(s): 1276


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.

Sample Input
2
10
20

Sample Output
7
19

题目的大意是说给定一个数并且这个数有可能很大,求这个数阶乘后的位数。
log10(n!)=log10(1*2*3…*n)=log10(1)+log10(2)+…+log10(n),这个公式当时看的时候想不明白,为什么取以10为底的对数就是这个数的位数,其实看log10(10)就明白了,这个数值是1,而位数正好就增加1。对log10(n!)的值取整加1就是n!的位数。n这个数如果不大的话这样做,10^7的话这样做肯定超时的。需用斯特林公式:
log10(n!) = log10(sqrt(2 * pi * n)) + n * log10(n / e)
当n>3的时候这个公式成立。当n<=3的时候位数为1。
在杭电上提交用第一个公式就能ac,代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int digit(int number)
{
    int i;
    double sum=0;
   
    for(i=1;i<=number;i++)
        sum+=log10(double(i));//根据公式得来的
    sum=floor(sum)+1;//向下取整函数
    return sum;
}
int main()
{
    int num;
    cin>>num;
    while(num--)
    {
        int dig;
        cin>>dig;
        cout<<(int)digit(dig)<<endl;
    }
   
    return 0;   
}
但是在北大上就TLE错误,只好用斯特林公式去做,ac。
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int digit(int number)
{
    double PI=acos(double(-1));//获取PI的值,原来还不知道有这个公式,对-1取反余弦函数。
    double e=exp(double(1));//获取自然底数e的值
    return int(log10(sqrt(2*PI*number))+number*log10(number/e))+1;
}
int main()
{
    int num;
    cin>>num;
    while(num--)
    {
        int dig;
        cin>>dig;
        cout<<(int)digit(dig)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值