HDOJ 1018(数论)

时间:2022-07-28
本文章向大家介绍HDOJ 1018(数论),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题意描述

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

思路

刚看到题的一瞬间,果断写了个高精度交了上去,TLE了,再看数据范围,嚯!1e7,然后就去翻了题解,发现是数论问题,求阶乘位数有两种方法:

1.10m<n!<10(m+1) 若求得M,则M+1为答案。对方程两边以10为底求对数,得M<log10(n!)<M+1,通过循环求值即可 2.斯特林公式:n! ≈ sqrt(2* n * pi)* (n/e)^n,则 M+1=(int)(0.5 * log(2.0 * n *PI)+n * log(n)-n)/(log(10.0)) )+1;

AC代码

方法1 复杂度O(n):

#include<vector>
#include<iostream>
#include<cstring> 
#include<queue>
#include<set>
#include<cmath>
#include<algorithm>
#define IOS ios::sync_with_stdio(false); cin.tie(0); 
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=15;
const int INF=0x3f3f3f3f;
int main() {
	IOS;
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		double ans=0;
		for(int i=1;i<=n;i++){
			ans+=log(i)/log(10);
		}
		cout<<(int)ans+1<<endl;
	}
    return 0;
}

方法2 复杂度O(1):

#include<vector>
#include<iostream>
#include<cstring> 
#include<queue>
#include<set>
#include<cmath>
#include<algorithm>
#define IOS ios::sync_with_stdio(false); cin.tie(0); 
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=15;
const double PI=3.1415926;
const int INF=0x3f3f3f3f;
int main() {
	IOS;
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		double ans=0;
		cout<<(int)((0.5*log(2.0*n*PI)+n*log(n)-n)/(log(10.0)))+1<<endl;
	}
    return 0;
}