水题poj1423 解题报告

本文介绍了一种通过数学公式和算法优化的方法,解决大规模阶乘位数计算问题,避免了直接高精度模拟带来的超时风险。通过引入自然对数和特殊数学常数,实现高效计算阶乘位数,特别适用于大规模数据处理场景。

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

poj1423是一道纯数学题目,原题的意思是输入一个数1 <= n <= 10^7 ,即需要用long来存储n,然后输出它的阶乘结果的位数。

这道题目的数据庞大,达10^7,高精度模拟显然不行。因此n我们必须另外想方法。
 要知道一个数字的位数是多少,我们可以用log10函数求得。例如,对于一个数,N=10,10!=3628800,而log10(3628800)=6.559763033,那么只要将这个数向上取整,就是7,就是10!的位数。

于是我们可以得到 log10(n!)=log10(1*2*3…*n)=log10(1)+log10(2)+…+log10(n)
但是用将一个一个数累加明显很超时,所以不能采用这种方法。


计算机程序设计艺术》中给出了另一个公式

 n! = sqrt(2*π*n) * ((n/e)^n) * (1 + 1/(12*n) + 1/(288*n*n) + O(1/n^3))

π = acos(-1)

e = exp(1)

两边对10取对数

忽略log10(1 + 1/(12*n) + 1/(288*n*n) + O(1/n^3)) ≈ log10(1) = 0

得到公式

log10(n!) = log10(sqrt(2 * pi * n)) + n * log10(n / e)


值得注意的是当n= 1的时候,输出结果为负,取整会为0。所以可以利用if语句来输出n= 1的情况。并且在log10(n!)的结果需要加1,再进行取整。

PS:反三角函数:asin(double) acos(double) atan(double);

自然数e=exp(1.0);


以下是源代码

#include <iostream>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);	
const double e = exp(1.0);		
int main()
{
	int n;
	long num;
	cin >> n;
	for(int i = 0; i < n; i++)
	{
		cin >> num;
		if(num == 1)
			cout << 1 << endl;
		else
			cout << int (log10(sqrt(2 * pi * num)) + num * log10(num / e) + 1) << endl;		//在log10(n!)的结果加上1,并强制转换类型取整
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值