poj-1001
2014-07-07 16:54
295 查看
//384K 0MS G++ #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 5200 struct BigNumber { char val[MAX]; // all chars are '0' or no char means '0' }; typedef struct BigNumber BigNumber; void bigNumberAddZero(BigNumber * p1, int zeroNum) { int length = strlen(p1->val); int i = 0; for (; i < zeroNum; i++) { p1->val[i+length] = '0'; } p1->val[i+length] = 0; } void bigNumberAdd(BigNumber * p1, BigNumber * p2, BigNumber * res) { int p1L = strlen(p1->val); int p2L = strlen(p2->val); // printf("bigNumberAdd %d %d\n", p1L, p2L); int maxLength = p1L > p2L ? p1L : p2L; if (p1L > p2L) { bigNumberAddZero(p2, p1L - p2L); } else if (p1L < p2L) { bigNumberAddZero(p1, p2L - p1L); } int carryFlag = 0; int i = 0; for (i = 0; i < maxLength; i++) { int v1 = (p1->val[i] - '0'); int v2 = (p2->val[i] - '0'); int sum = v1 + v2 + carryFlag; if (sum >= 10) { carryFlag = 1; res->val[i] = sum - 10 + '0'; } else { carryFlag = 0; res->val[i] = sum + '0'; } } if (carryFlag == 1) { res->val[maxLength] = '1'; carryFlag = 0; res->val[maxLength+1] = 0; } else { res->val[maxLength] = 0; } } void bigNumberMultiplyS(BigNumber * p1, int p2, BigNumber * res) { int carryVal = 0; int length = strlen(p1->val); for (int i = 0; i < length; i++) { int val = p1->val[i] - '0'; int result = val*p2 + carryVal; carryVal = result/10; res->val[i] = result%10 + '0'; } if (carryVal > 0) { res->val[length] = carryVal + '0'; res->val[length+1] = 0; } } void bigNumberAppendZero(BigNumber * p1, int zeroNum) { if (!zeroNum) { return; } for (int i = strlen(p1->val); i >= 0; i--) { p1->val[i+zeroNum] = p1->val[i]; p1->val[i] = '0'; } } BigNumber b1; BigNumber b2; BigNumber b3; BigNumber res; BigNumber tmp; BigNumber tmp2; void printBigNumber(BigNumber * p1) { char beginPrint = 0; if (strlen(p1->val) == 0) { printf("0"); } else { for (int i = strlen(p1->val)-1; i >= 0; i--) { if (beginPrint) { printf("%c", p1->val[i]); } else { if (p1->val[i] != '0') { // first counter 1~9 beginPrint = 1; printf("%c", p1->val[i]); } } } } printf("\n"); } void bigNumberMultiply(BigNumber * p1, BigNumber * p2, BigNumber * res) { // printf("bigNumberMultiply\n"); int p1L = strlen(p1->val); int p2L = strlen(p2->val); BigNumber * big = p1L > p2L ? p1 : p2; BigNumber * small = p1L <= p2L ? p1 : p2; int length = p1L < p2L ? p1L : p2L; for (int i = 0; i < length; i++) { // printf("bigNumberMultiply %c\n", small->val[i]); int S = small->val[i] - '0'; memset(&tmp, 0, sizeof(BigNumber)); if (S) { // this check better in bigNumberMultiplyS bigNumberMultiplyS(big, S, &tmp); bigNumberAppendZero(&tmp, i); memcpy(&tmp2, res, sizeof(BigNumber)); bigNumberAdd(&tmp2, &tmp, res); } } } void reset() { memset(&b1, 0, sizeof(BigNumber)); memset(&b2, 0, sizeof(BigNumber)); memset(&b3, 0, sizeof(BigNumber)); memset(&res, 0, sizeof(BigNumber)); memset(&tmp, 0, sizeof(BigNumber)); memset(&tmp2, 0, sizeof(BigNumber)); } void bigNumberExp(BigNumber * p1, int N, BigNumber * res) { // printf("N %d\n", N); if (N == 0) { res->val[0] = '0'; res->val[1] = 0; return; } memcpy(res, p1, sizeof(BigNumber)); int i = 2; // printf("%d %d\n", i, N); for (; i <= N; i++) { // printf("%d\n", i); bigNumberMultiply(p1, res, &tmp2); // printBigNumber(&tmp2); memcpy(res, &tmp2, sizeof(BigNumber)); memset(&tmp2, 0, sizeof(BigNumber)); } // printf("END\n"); } void printBigNumberWithPoint(BigNumber * p1, int smallNum) { int length = strlen(p1->val); if (!length) { printf("0\n"); return; } for (int i = length - 1; i >= 0; i--) { // remove prefix 0; eg 004459900 -> 4459900 if (p1->val[i] != '0') { p1->val[i+1] = 0; break; } } length = strlen(p1->val); if (smallNum <= 0) { // no small number for (int i = length-1; i >= 0; i--) { printf("%c", p1->val[i]); } printf("\n"); return; } else if (smallNum >= length) { // all small number, remove all after 0, eg 3343708000 -> 3343708 int i = 0; for (; i <= length-1; i++) { if (p1->val[i] != '0') { break; } } int printEnd = i; int frontZeroNum = smallNum - length; printf("."); for (int i = 1; i <= frontZeroNum; i++) { printf("0"); } for (int i = length-1; i >= printEnd; i--) { printf("%c", p1->val[i]); } } else { //bigNum.smallNumber int printEnd = 0; for (int i = 0; i < smallNum; i++) { if (p1->val[i] != '0') { printEnd = i; break; } } for (int i = length - 1; i >= printEnd; i--) { printf("%c", p1->val[i]); if (i == smallNum) { printf("."); } } } printf("\n"); } int main() { int N; reset(); while(scanf("%s %d", b1.val, &N) != EOF) { int i; int length = strlen(b1.val); // for (int i = length - 1; i >= 0; i--) { // if (b1.val[i] == '.') { // break; // } else if (b1.val[i] != '0') { // b1.val[i+1] = 0; // break; // } // } // find the '.' location for (i = 0; i < length; i++) { if (b1.val[i] == '.') { break; } } // find the length of small number int smallNumberLength; if (i >= length) { // '.' do not exist, no small number smallNumberLength = 0; } else { // get the length of small number, special case: 1.0000 -> 1 for (int j = length-1; j >= i; j--) { if (b1.val[j] == '.') { // no small number. eg 1.0000 b1.val[j] = 0; smallNumberLength = 0; break; } else if (b1.val[j] != '0') { b1.val[j+1] = 0; smallNumberLength = j - i; break; } } } //remove '.' if (smallNumberLength == 0) { } else { for (; i < length; i++) { b1.val[i] = b1.val[i+1]; } } int noZeroBegin = 0; int noZeroEnd = strlen(b1.val)-1; //remove front 0, e.g, 0022343200 -> 22343200 for (; b1.val[noZeroBegin] == '0'; noZeroBegin++) { } // //remove append 0, e.g, 22343200 -> 223432 // for (; b1.val[noZeroEnd] == '0'; noZeroEnd--) { // } strncpy(b3.val, b1.val + noZeroBegin, noZeroEnd - noZeroBegin + 1); // printf("%s %d\n", b1.val, smallNumberLength); // printf("%s %d %d %d\n", b3.val, smallNumberLength, noZeroBegin, noZeroEnd); length = strlen(b3.val); for (i = 0; i <= (length/2)-1; i++) { char tmp = b3.val[i]; b3.val[i] = b3.val[length - i-1]; b3.val[length - i-1] = tmp; } // memcpy(&b2, &b1, sizeof(BigNumber)); // bigNumberAppendZero(&b1, 4); // bigNumberAdd(&b1, &b2, &b3); // bigNumberAdd(&b3, &b2, &b1); // bigNumberMultiplyS(&b1, 5, &b2); // bigNumberMultiply(&b1, &b2, &b3); smallNumberLength *= N; bigNumberExp(&b3, N, &b2); // printBigNumber(&b3); // printBigNumber(&b2); // printBigNumberWithPoint(&b3, smallNumberLength); printBigNumberWithPoint(&b2, smallNumberLength); // printBigNumber(&b3); // printf("%s %d\n", b1.val, smallNumberLength); // printf("%s %d\n", b2.val, smallNumberLength); // printf("%s %d\n", b3.val, smallNumberLength); reset(); } }
384K 0MS G++
本来想捏个软柿子来着,以为1001应该是个水题,谁想到竟然是我以前望而生畏的大数乘法(以前最多大数加减),
这道题是典型的思路上是水题(小学乘法),但是实现上绝对考察细节的一道题。
基本人人都知道是要用字符串来模拟求值,但是脑子里有雏形和真写出来差的不是一点半点的。
并且题目的输出要求不能有多余0等也进一步增加了AC的难度,记录一下思路的了:
首先是开个大的字符串数组来存储大数(直接给开了5000,反正内存够多), 专门搞了一个bigNumber封装,不过也就是个皮罢了。
输入也是字符串A,长度为L,首先要找到 ‘.’ 的位置,如果没找到,那么这个数一定是整数,小数位长度就是0.
如果找到了'.', 那就说明是一个实数,要先做一件事,就是把小数位后面跟的0清除,比如 1.01000 -> 1.01(貌似不会出现 0XX.XX 这样的情况,不过还是考虑了), 这样做以后才能求真正的小数位的长度。然后就是把 '.' 给去掉,得到一个整数,用作以后的运算,
这里为了运算的方便,用小端保存法(要把A前后颠倒一下),即数组前面的位置存储整数的低位,比如 1234 保存在数组C里就是 C[0] = 4 C[1] = 3 C[2] = 2 C[3] = 1,这样在以后的大整数加法中会很方便,不然每次都要考虑数位对齐,
要实现的大数操作有:
1. 两个大数相加: 小学加法,搞一个进位标记参与运算, 不过要扩展一下数位短的大数。
2. 一个大数和某个一位整数相乘;小学乘法 要搞一个进位变量保存进位(0~9)。
3. 某个大数增加10的N此方倍:向右平移N位就可以,空出来的补零。
4. 两个大数相乘: 取数位短的大数作为乘数,可以节省些时间,其他的操作就是小学乘法步骤,用前三种操作来组合实现, 每次进行一次单位数乘法,然后累加到
乘积和中,同时适当的乘以10的N次方。
4. 大数整数次方运算: 懒得搞乘法优化了(即 ,若N为偶数, X的N次方 = (X的N/2次方的平方)的平方, 若为奇数,再额外乘一次X,这样可以大大减少乘的次数)
直接乘了,反正时间够,次数最多25.
最后输出结果的时候,要算一下结果的小数位S应该是多少(就是次方数*X原来的小数位长度),如果小数位是0,直接输出整数。
如果小数位大于了结果R的长度L(及只有小数),那么就前面加一个 '.',然后输出 S-L个0,再输出R,注意最后连续0不能输出 及0.0021212300 -> 0.0021212300
如果既有整数又有小数,那么也要考虑小数后面连续0的情况,在输出时还要插入 '.'。
这道题是很经典的题,比较考基本功和细致程度,啥时侯我要能一遍写对,估计在细致度就差不多了(其实不太现实,目前其实软件的开发方法很大程度是试错法,
这其实是人的思维结构决定的,除非在脑子里已经把code全部打磨出来了).
相关文章推荐
- POJ 1001 求高精度幂
- hdoj1063&&poj1001 Exponentiation(大数据的处理,浮点数的幂高精确度表示)
- POJ 1001解题报告
- poj 1001
- POJ 1001 Exponentiation (Java高精度)
- java高精度 poj1001
- 【原】 POJ 1001 Exponentiation 大整数乘法 解题报告
- POJ1001 Exponentiation(高精度幂)
- poj 1001 a+b
- poj 1001 Exponentiation
- poj 1001 Exponentiation
- 菜鸟学便成 : poj 1001 Exponentiation
- poj-1001 Exponentiation
- POJ 1001
- POJ 1001
- POJ 1001 Exponentiation
- POJ 1001 Exponentiation(浮点数的n次方)
- poj 1001 Exponentiation(高精度运算)
- POJ1001
- POJ 1001 高精度指数运算