牛客網刷題(四) 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;
}
我們可以看出儲存一個大數,有很多種方法可以處理,比如用陣列,用容器