题目:写一个算法实现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;
}
我们可以看出保存一个大数,有很多种方法可以处理,比如用数组,用容器