求幂的位数,求阶乘的位数

笔者总结自己的思路,有以下两种方法解决求幂的长度,求阶乘的长度。从而解决形如
请你计算数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所能表示的范围,无法存储哨兵,这类情况第二种方法也无能为力。

发布了97 篇原创文章 · 获赞 101 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/practical_sharp/article/details/104139920