UVa 1185

UVa 1185

題目

http://domen111.github.io/UVa-Easy-Viewer/?1185

有 $n$ 筆測資,每筆測資包含一個數字 $m$ ,求 $m!$ 是幾位數

想法

如果只給一個數字 $p$ ,要求 $p$ 是幾位數我們可以用高中學到的 $log_{10}p +1$ 的整數得到答案

根據 $log$ 的性質, $log_{10}{(a*b)}$ = $log_{10}{a} + log_{10}{b}$

在階乘計算上數字成長速度很快就會超過我們能儲存的大小,所以我們要利用前面提到的 $log$ 性質

要計算 $m!$ 的位數,等同於 $floor(1+\sum_{x=1}^{m}{log_{10}{x}})$

其中, $floor$ 表示取整數

Code 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
#include<cmath>
using namespace std;
int n,m;
int main(){
cin>>n;
while(n--){
cin>>m;
double ans=0;
for(int i=1 ; i<=m ; i++){
ans+=log10(i);
}
cout<<(int)ans+1<<'\n';
}
return 0;
}

時間複雜度分析

每筆測資都需要花 $O(m)$ 的時間計算

總時間複雜度 $O(nm)$

Code 2

我們可以將所有答案都先算起來,這樣每次詢問就可以直接回答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
#include<cmath>
using namespace std;
const int N = 10000005;
int n,m;
int ans[N];
double tmp;
int main(){
for(int i=1 ; i<N ; i++){
tmp+=log10(i);
ans[i]=(int)tmp+1;
}
cin>>n;
while(n--){
cin>>m;
cout<<ans[m]<<'\n';
}
return 0;
}

時間複雜度分析

預先處理答案的時間複雜度為 $O(N)$

每筆詢問的時間複雜度為 $O(1)$

總時間複雜度為 $O(N + n)$