這算是本BLOG的第一篇文章吧,算法這一塊荒廢了很長時間,,這份代碼剛開始寫的時候,剛輸完main時,整個人都是蒙的,不知該如何往下走。
好在成功寫完了。由於沒啥狀態,所以這個高精+功能非常簡單,只能+,不支持負數。
這裏說一下位壓的思想,一般的評測機都是32位的,所以一個int能儲存32位數據。
再來看一看0 ~ 9,二進制分別對應0000~1001,所以一個4位二進制正好可以存儲,所以這裏就4位存一個數字,32位正好8個。
首先來設計輸入函數:
inline bool read (int & ret, int bit) {//存到一個32位整數裏
int c = getchar();
if (c < '0' || c > '9') return 0;
c = c - '0';
c <<= (bit << 2); //bit * 4
ret |= c;
return 1;//該數是否讀取成功,用於while的結束
}
返回一個bool,表示當前輸入是否成功,一般返回也就代表一行輸入完了。
函數思想和快速讀入差不多,也是getchar,然後變成整數。一個int可以存8個數字,其中參數bit(新京報命名)表示存爲第幾位數字。
讀寫好了,接下來就是取,取數字的話分爲兩種:
- 對於一個單獨的int取數
- 對於一整個(高精度)數組取數
第一種比較好實現,但是會出一小點點問題:
inline void get_num (int n_arr, int bit, int & ret) {//取數字
ret = (n_arr >> (bit << 2)) & 15;
}
因爲我們存數字是從高位開始讀取的,高位的數字優先存儲在int中的低位
比如我輸入1234,讀取函數返回的int爲171855,二進制爲0100 0011 0010 0001,十六進制爲4321
可以看到正好反過來了,所以我們搞不清楚某一個int中到底存儲了多少個有效數字。
這種存儲方式中,1234和12340的int值是相等的,不過我們可以通過記錄每一個高精度數字的總位數來避免這種情況,理由是:
- 只要不是高精數的最後幾位不滿8個數的,其他高位上的int都能存儲8位整數
- 當某個int存儲了不到8個數時,往前(高位)的位都是全0填充
所以只要單開兩個變量存儲數字的總位數即可。
先講講第二種取數字
inline void get_arr_num(int * arr, int bit, int & ret) {//對一個高精度數字取出某一位
-- bit;
int a = bit / 8, b = bit - a * 8;
get_num (arr[a], b, ret);
}
這裏數字位數是從1開始的,注意。。
參數的解釋:arr數組表示某一個高精度數,bit是取這個高精度數字的第幾位,最高位是1,依次往下。ret就是返回。。。
a代表要取的數字在第幾個數組裏,向下取整,因爲高位數字在數組中的下標更小,b表示該位數字存儲在32位int中的第幾個。
最後最後,就是main了,主函數中包含了這幾個部分:
- 讀入兩個高精度操作數
- 循環開始從這兩個數字的最低位相加,一直加到最大的那個數的最高位
- 保存結果,輸出
這裏直接放全部的代碼吧。。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int num_a [505];
int num_b [505];
inline bool read (int & ret, int bit) {//存到一個32位整數裏
int c = getchar();
if (c < '0' || c > '9') return 0;
c = c - '0';
c <<= (bit << 2); //bit * 4
ret |= c;
return 1;//該數是否讀取成功,用於while的結束
}
inline void get_num (int n_arr, int bit, int & ret) {//取數字
ret = (n_arr >> (bit << 2)) & 15;
}
/*inline int get_num_long (int n) {//查詢一個數字中的有效數字存儲個數
int r = 8,z = 15 << 28;
while (!(n & z)) {
-- r;
z >>= 4;
}
return r;
}*/
inline void get_arr_num(int * arr, int bit, int & ret) {//對一個高精度數字取出某一位
-- bit;
int a = bit / 8, b = bit - a * 8;
get_num (arr[a], b, ret);
}
int main () {
int b_p = 0, l_p = 0;
int a_l = 0, b_l = 0;
while (read (num_a [b_p], l_p)) {//讀取數字a
++ l_p; a_l ++;
if (l_p == 8) {
l_p = 0;
++ b_p;
}
}
b_p = 0, l_p = 0;
while (read (num_b [b_p], l_p)) {//讀取數字b
++ l_p; b_l ++;
if (l_p == 8) {
l_p = 0;
++ b_p;
}
}
string OP;//OutPut
int Cin = 0;//進位
int a, b, c;//a的某位,b的某位,c=a+b
for (int i = a_l,j = b_l; (i > 0) | (j > 0); -- i, -- j) {//最低位開始相加
if (i > 0) {
get_arr_num (num_a, i, a);
} else { //判斷是否超出最高位
a = 0;
}
if (j > 0) {
get_arr_num (num_b, j, b);
} else {
b = 0;
}
c = a + b + Cin;
if (c >= 10) {//是否進位
Cin = 1;
OP = (char) (c - 10 + '0') + OP;
} else {
Cin = 0;
OP = (char) (c + '0') + OP;
}
}
if (Cin) cout << '1';//判斷最高位是否進位
cout << OP;
return 0;
}
當然,所有的思想都是自己想出來的,這份代碼也只是臨時起意,並沒有經過評測,僅供參考,如有BUG,也算正常,還請指點