Pro.ID10185 TitleBig Numbers Title链接http://10.20.2.8/oj/exercise/problem?problem_id=10185 AC0 Submit0 Ratio- 时间&空间限制描述Sample Problem: FactorialGiven N (1 <= N <= 200), calculate N! exactly. The ProblemAll built-in integers have a limited value range. Sometimes, a problem will ask for the calculation of a number which is outside that range for all the available numbers. For example, 200! has 375 digits and would require a 1246 bit number (if one chose to store the number in binary) to hold it, which is unlikely to be available as a native datatype in contest environments. Thus, what is needed is a way to store and manipulate large numbers. The StructureOne method to store these numbers is actually fairly straight-forward: a list of numbers and a sign. This list can be either an array, if an upper bound is known on the length of the numbers, or a linked list, if the numbers have no upper bound. One way to think of this storage method is keeping the `digits' of a number in a huge base. Let b be the base in which the number is stored, and a0, a1, ..., an be the digits stored. Then, the number represented is (-1)sign times (a0+ b1a1+ b2a2+ ... + bna n). Note that a0, a1, ..., an must be in the range 0..b-1. Generally, the base b is selected to be a power of 10, as it makes displaying the number very easy (but don't forget the leading zeroes). Note that this representation stores the numbers in the order presented: a0, then a1, then a2, etc. This is the reverse of the obvious ordering, and, for linked lists, it may be worthwhile to keep a deque, as some of the algorithms will want to walk through the list in the opposite order. OperationsFor this data structure, figuring out how to do the various operations requires recalling how to do the operations by hand. The main problem that one has to be aware of is overflow. Always make sure that every addition and multiplication will not result in an overflow, or the entire operation will be incorrect. For simplicity, the algorithms presented here will assume arrays, so if a number is a0, a 1, ..., ak, then for all i > k, ai = 0. For linked lists, the algorithms become a bit more difficult. In addition, the result bignums are assumed to be initialized to be 0, which will not be true in most cases. ComparisonTo compare two numbers a0, a1, ..., an and b0, b1, ..., bk, with signs signA and signB goes as follows: AdditionGiven two numbers a0, a1, ..., an and b0, b1, ..., bk, calculate the sum and store it in c. In order for addition to be possible, 2 x b must be smaller than the largest representable number. If the numbers have opposite signs, then: calculate which is larger in absolute value, subtract the smaller from the larger, and set the sign to be the same as the larger number. Otherwise, simply add the numbers from 0 to max ( n, k), maintaining a carry bit. Note that if it is known that both numbers have positive sign, the operation becomes much simpler and doesn't even require the writing of absolute_subtract. Here is the pseudocode for addition: SubtractionSubtraction is simple, given the addition operation above. To calculate A - B, negate the sign of B and add A and (-B). Multiplication by scalarTo multiply a bignum A by the scalar s, if |s x b| is less than the maximum number representable, can be done in a similar manner to how it is done on paper. Multiplication of two bignumsMultiplying two numbers, if b2 is below the largest representable number is a combination of scalar multiplication and in-place addition. Basically, multiply one of the numbers by each digit of the other, and add it (with the appropriate offset) to a running total, the exact same way one does long multiplication on paper. Division by scalarIn order to divide the bignum b by a scalar s, s x b must be representable. Division is done in a very similar manner to long division. Division by bignumThis is similar to division by scalar, except the division is done by multiple subtractions. Note that if b is large, this particular formulation takes too long. Binary SearchBinary search is a very helpful thing in general, but in particular for bignums, as operations are expensive. Given an upper and lower bound, check the mean of those two to see if it is above or below those bounds, and cut the range by (almost) a factor of 2. For example, if b is large, then division by a bignum is slow to do by the method above, but the following works well: 输入This is NOT a problem , but a course. Read it , but not Submit 输出Description Sample Problem: FactorialGiven N (1 <= N <= 200), calculate N! exactly. The ProblemAll built-in integers have a limited value range. Sometimes, a problem will ask for the calculation of a number which is outside that range for all the available numbers. For example, 200! has 375 digits and would require a 1246 bit number (if one chose to store the number in binary) to hold it, which is unlikely to be available as a native datatype in contest environments. Thus, what is needed is a way to store and manipulate large numbers. The StructureOne method to store these numbers is actually fairly straight-forward: a list of numbers and a sign. This list can be either an array, if an upper bound is known on the length of the numbers, or a linked list, if the numbers have no upper bound. One way to think of this storage method is keeping the `digits' of a number in a huge base. Let b be the base in which the number is stored, and a0, a1, ..., an be the digits stored. Then, the number represented is (-1)sign times (a0+ b1a1+ b2a2+ ... + bna n). Note that a0, a1, ..., an must be in the range 0..b-1. Generally, the base b is selected to be a power of 10, as it makes displaying the number very easy (but don't forget the leading zeroes). Note that this representation stores the numbers in the order presented: a0, then a1, then a2, etc. This is the reverse of the obvious ordering, and, for linked lists, it may be worthwhile to keep a deque, as some of the algorithms will want to walk through the list in the opposite order. OperationsFor this data structure, figuring out how to do the various operations requires recalling how to do the operations by hand. The main problem that one has to be aware of is overflow. Always make sure that every addition and multiplication will not result in an overflow, or the entire operation will be incorrect. For simplicity, the algorithms presented here will assume arrays, so if a number is a0, a 1, ..., ak, then for all i > k, ai = 0. For linked lists, the algorithms become a bit more difficult. In addition, the result bignums are assumed to be initialized to be 0, which will not be true in most cases. ComparisonTo compare two numbers a0, a1, ..., an and b0, b1, ..., bk, with signs signA and signB goes as follows: AdditionGiven two numbers a0, a1, ..., an and b0, b1, ..., bk, calculate the sum and store it in c. In order for addition to be possible, 2 x b must be smaller than the largest representable number. If the numbers have opposite signs, then: calculate which is larger in absolute value, subtract the smaller from the larger, and set the sign to be the same as the larger number. Otherwise, simply add the numbers from 0 to max ( n, k), maintaining a carry bit. Note that if it is known that both numbers have positive sign, the operation becomes much simpler and doesn't even require the writing of absolute_subtract. Here is the pseudocode for addition: SubtractionSubtraction is simple, given the addition operation above. To calculate A - B, negate the sign of B and add A and (-B). Multiplication by scalarTo multiply a bignum A by the scalar s, if |s x b| is less than the maximum number representable, can be done in a similar manner to how it is done on paper. Multiplication of two bignumsMultiplying two numbers, if b2 is below the largest representable number is a combination of scalar multiplication and in-place addition. Basically, multiply one of the numbers by each digit of the other, and add it (with the appropriate offset) to a running total, the exact same way one does long multiplication on paper. Division by scalarIn order to divide the bignum b by a scalar s, s x b must be representable. Division is done in a very similar manner to long division. Division by bignumThis is similar to division by scalar, except the division is done by multiple subtractions. Note that if b is large, this particular formulation takes too long. Binary SearchBinary search is a very helpful thing in general, but in particular for bignums, as operations are expensive. Given an upper and lower bound, check the mean of those two to see if it is above or below those bounds, and cut the range by (almost) a factor of 2. For example, if b is large, then division by a bignum is slow to do by the method above, but the following works well: Input This is NOT a problem , but a course. Read it , but not Submit Output This is NOT a problem , but a course. Read it , but not Submit Sample Input This is NOT a problem , but a course. Read it , but not Submit Sample Output This is NOT a problem , but a course. Read it , but not Submit Source 样例输入This is NOT a problem , but a course. Read it , but not Submit 样例输出This is NOT a problem , but a course. Read it , but not Submit 作者 |