//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全部打磨出来了).