求冪的位數,求階乘的位數

筆者總結自己的思路,有以下兩種方法解決求冪的長度,求階乘的長度。從而解決形如
請你計算數a的b次冪共有多少位(十進制的數)!”
N! (N的階乘) 是非常大的數,計算公式爲:N! = N * (N - 1) * (N - 2) * … * 2 * 1)。現在需要知道N!有多少(十進制)位。”之類的問題。

方法一:調用log10()函數

解決階乘的位數

int digit(int n)//求數n的階乘的長度
{
   double length = 0;
   for(int i =1;i<=n;++i)
	   length += log10((double)i);
   //此處爲進一法,length爲double型變量,沒有絕對的整數值,只有可能能是逼近某個整數
   return (int)(length+1); 
}

解決冪的位數

和解決階乘的位數相似,區別在於兩個變量

int digit(int a, int b)//求數a的b次冪的長度
{
   double length = 0;
   for(int i =1;i<=b;++i)
	   length += log10((double)a);
   //此處爲進一法,length爲double型變量,沒有絕對的整數值,只有可能能是逼近某個整數
   return (int)(length+1); 
}

方法二:設哨兵對10取餘法

解決階乘的位數

題目來源

http://acm.nefu.edu.cn/problemShow.php?problem_id=65

Description

N! (N的階乘) 是非常大的數,計算公式爲:N! = N * (N - 1) * (N - 2) * … * 2 * 1)。現在需要知道N!有多少(十進制)位。

Input

每行輸入1個正整數N。0 < N < 1000000

Output

對於每個N,輸出N!的(十進制)位數。

Sample Input

1
3
32000
1000000

Sample Output

1
1
130271
5565709

思路

設置一個很大的數,在對階乘不斷更新的過程中一旦超過這個數就dui10取餘,同時更新長度,以防止階乘越界。

根據0 < N < 1000000 ,筆者定義int64_t M = 1e10
const int64_t M = 1e10; 
AC代碼
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<inttypes.h>
using namespace std;
int64_t sum = 1;const int M = 1e10;//設置哨兵
int main(){
    int n;//n<=1000000
    while(cin>>n){
		if(n<=3) cout<<1<<endl;//0,1,2,3的階乘的位數爲1位
		else{
			int length = 0;sum = 1;//length爲階乘的長度
			for(int i=2;i<=n;i++){
				while(sum > M){
					sum /= 10;
					length++;
				}
				sum *= i;
			}
			while(sum){
				sum /= 10;
				length++;
			}
			cout<<length<<endl;
		}
    }
    return 0;
}

解決冪的長度

和上述代碼下相比只是只改變了一點點、

題目來源

http://acm.nefu.edu.cn/problemShow.php?problem_id=94

Description

請你計算數a的b次冪共有多少位(十進制的數)!

Input

輸入數據有多組,每組二個正整數分別爲a和b,其中(1<=a<=10000,1<=b<=10000)

Output

輸出a^b(a的b次冪)的值共有多少位?

Sample Input

2 3
1 1
10 5

Sample Output

1
1
6

AC代碼
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<inttypes.h>
using namespace std;
int64_t sum = 1;const int M = 1e10;
//計算數a的b次冪共有多少位 其中(1<=a<=10000,1<=b<=10000)
int64_t getpowLen(int a,int b)
{
	if(b == 0)  return 1;
	int64_t ans = 0;int64_t sum = 1;//ans存放長度,sum用於更新冪
	for(int i=1;i<=b;i++){
		while(sum > M){
			sum /= 10;
			ans++;
		}
		sum *= a;
	}
	while(sum){ //求最後餘下的長度
		sum /= 10;
		ans++;
	}
	return ans;
}
int main(){
    int a,b;
    while(cin>>a>>b)
		cout<<getpowLen(a,b)<<endl;
    return 0;
}

總結

筆者認爲運用log10()函數更加準確,同時也對算術基本定理有了新的運用。
對於第二種算法,如果題目給出的n的長度最大爲1018,那麼哨兵會爆出int64_t所能表示的範圍,無法存儲哨兵,這類情況第二種方法也無能爲力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章