这算是本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,也算正常,还请指点