1. 程式人生 > >牛客網刷題(四) 2^n(n>=512)

牛客網刷題(四) 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;
}

我們可以看出儲存一個大數,有很多種方法可以處理,比如用陣列,用容器