牛客网刷题(四) 2^n(n>=512)

题目:写一个算法实现2的n次方(n>=512)。

           输入:一个数字n

           输出:2的n次方

思路:想要求2^n的值我们首先可能会想到的办法,就是直接计算,但是由于2^n(n>=512)的值过大,没有办法用平常的类型进行存储,所以编译器会直接显示值为0,导致结果错误,那么此时,我们就该思考,应该用什么来存储这个过大的值,我们首先可能会考虑到数组,那么我们就先用数组做一下这道题。那么现在我们要考虑怎么实现这个2的n次方的算法,首先申请一个大数字来存储这个很长的数字,2的n次方就是一个不断乘2的过程,并且我们首先得到的是个位数,如果个位数大于10,需要与10做除法运算,算出需要进上去的数字,再得到十位数字,那么如果我们把先得到的数字存储数组下标为0的位置,那么到时候输出所得数字时,会存在数字倒序的问题,怎么解决这个问题呢?可以正序存储数字,倒序打出,或者,直接倒序存储数字,正序打出,两者思路基本一致,在这里,我采用的是倒序存储数字,正序打出。解决完这个问题后,我们大致就有了思路:

1.申请一个数组,并且初始化,a[1000]={0};   在设一个整型变量  int  b=0; 来存储进位数字;

2.要求2的n次方就是n个2相乘,所以打的循环条件应该是for(int  i=0;i<n;i++);

3.因为是倒序存储,所以我们应该设数组的最后一个元素a[999]=1,因为2^0=1,如果n=0,那么我们也应该输出1;

4.第二个遍历条件应该是数组的长度,设j=999;while(j>=0),因为你不知道你要输出的数有多长,所以要将数组的长度遍历一遍,不然可能有数字被丢弃,不能被存储到,可是这也增加了时间复杂度,这也为我们优化算法提供了思路;

5.剩下就是乘方算法具体的核心,我们先算出乘以2并加上进位数后的数字,但是我们最后数组中要存储的数字肯定不是这个,因为我们要模拟的是数组的每一位存储数组的一位数,否则又变成和原来一样的情况。得到这个数字后,先给这个数字除以10得到进位数,在给这个数字取余,得到最后这个数组中要存储的值,再给j--,算后面的位数,以此类推;

6.最后就剩下将数组打印出来,我们现将数组正序遍历,直到第一个不为0的数字停止,再将数组打印出来。

代码如下:

#include<iostream>
#include<vector>
using namespace std;
void fun4(int n)
{
	const int x = 2;
	int a[1000] = { 0 };
	int b = 0;
	a[999] = 1;
	for (int i = 0; i < n; i++)
	{
		int j = 999;
		while (j >= 0)
		{
			a[j] = a[j] * x + b;
			b = a[j] / 10;
			a[j] = a[j] % 10;
			j--;
		}
	}
	int i = 0;
	for (i = 0; i < 1000; i++)
	{
		if (a[i] != 0)
		{
			break;
		}
	}
	for (; i < 1000; i++)
	{
		cout << a[i];
	}
	cout << endl;
}
int main()
{
    int n = 0;
	cin >> n;
	fun4(n);
    return 0;
}

结果如下:

因为这种算法的时间复杂度实在过大,我们需要将这种算法改进一下,这种算法的时间复杂度过大,就是因为在存储数字时,每次都遍历了999,主要是因为数组没办法知道自己的数组内到底不为0,在这里我对循环进行了优化,但是,2^n的算法发生了一点小变化。

代码改进为:

#include<iostream>
#include<vector>
using namespace std;
void fun5(int n)
{
	char b[1000];
	int a[1000] = { 0 };
	a[0] = 1;
	int num = 1,j;
	for (int i = 0; i < n; i++)
	{
		for (j = 0; j < num; j++)
		{
			a[j] = a[j] * 2;
		}
		
		for (j = 0; j < num; j++)
		{
			if (a[j]>=10)
			{
				a[j + 1] = a[j] / 10 + a[j + 1];
				a[j] = a[j] % 10;
			}
		}
		if (a[j] != 0)
		{
			num++;
		}
	}
	for (j = 0; j < num; j++)
	{
		b[j] = a[num-1-j] + '0';
	}
	b[j]='\0';
}
int main()
{
    int n = 0;
	cin >> n;
	fun5(n);
    return 0;
}

 

这道题还可以用容器来做,用容器中带的函数来计算容器中一共有几个数字 

#include<iostream>
#include<vector>
using namespace std;
vector<int> vc;
void fun3(int n)
{
	vc.push_back(1);

	for (int i = 0; i < n; i++)
	{
		int size = vc.size();
		int b = 0;
		for (int j = 0; j < size; j++)
		{
			vc[j] = vc[j] * 2 + b;
			b = vc[j] / 10;
			vc[j] = vc[j] % 10;	
		}
		if (b != 0)
		{
			vc.push_back(b);
		}
	}
}
int main()
{
    int n = 0;
	cin >> n;
	fun3(n);
	vector<int>::reverse_iterator it = vc.rbegin();
	for (; it < vc.rend(); it++)
	{
		cout << *it;
	}
	cout << endl;
    return 0;
}

我们可以看出保存一个大数,有很多种方法可以处理,比如用数组,用容器

猜你喜欢

转载自blog.csdn.net/weixin_42736024/article/details/84110023