solution for POJ 1001

  http://poj.org/problem?id=1001

  POJ的前几道题理解起来很简单,算法也不复杂,只是需要花很长的时间去调试。1001本质上就是一个大数运算的问题,大数乘法的问题可以采用分治法,具体参考这篇文章:http://blog.csdn.net/tjsinor2008/article/details/5625849。代码如下:

  1 #include<stdio.h>
  2 #include<memory.h>
  3
  4 unsigned char a[200],b[200],c[200];
  5 int lenA,lenB,maxlen,digit,p;
  /*a[200],b[200],c[200]用来存储数据,底数去掉小数点以后存储在a里面,从高位到低位每一位储存一个数字,b保存每次乘法的结果,将该结果加上小数点并去掉0前缀和后缀存在c里面,最后打印出来。最开始用的char*,而不是char[],后来发现因为最后计算的结果往往都是很长的字符串,会导致字符串b和c有一部分重合,计算结果不正确。最终改为数组以后解决了这个问题。*/
  7 int strlength(char* s)
  8 {
  9     int result=0;
 10     while(*s!=0)
 11     {
 12         result++;
 13         s++;
 14     }
 15     return result;
 16 }
 17 /*乘法函数的关键在于对c[i+j+1]和c[i+j]修改赋值的这个循环,仔细想想不难理解。需要注意的是c[i+j]+=(c[i+j+1]-‘0‘)/10这一句可能会导致在循环结束的时候有数组的元素大于‘9’,所以最后需要再重新对计算结果从后往前遍历一遍,将该进位的进位。*/
 18 void mul(unsigned char* a,unsigned char* b)
 19 {
 20     int i,j;
 21     lenA=strlength(a);
 22     lenB=strlength(b);
 23     maxlen=lenA+lenB;
 24
 25     for(i=0;i<maxlen;i++)
 26     {
 27         c[i]=‘0‘;
 28     }
 29     c[maxlen]=‘\0‘;
 30
 31     for(i=0;i<lenA;i++)
 32     {
 33         for(j=0;j<lenB;j++)
 34         {
 35             c[i+j+1]+=(a[i]-‘0‘)*(b[j]-‘0‘);
 36             c[i+j]+=(c[i+j+1]-‘0‘)/10;
 37             c[i+j+1]=(c[i+j+1]-‘0‘)%10+‘0‘;
 38         }
 39     }
 40
 41     for(i=maxlen-1;i>=0;i--)
 42     {
 43         if(c[i]>‘9‘)
 44         {
 45             c[i-1]+=(c[i]-‘0‘)/10;
 46             c[i]=(c[i]-‘0‘)%10+‘0‘;
 47         }
 48     }
 49
 50     memcpy(b,c,maxlen+1);
 51 }
 52 /*把计算结果加上小数点并去除掉前置和后置的不必要的0。为避免不必要的麻烦,我先把小数点加到该加的位置上,然后再处理多余的0.需要注意的是如果最后结果是以‘.’也就是以小数/点结尾(比如底数本来就是整数),那么这个小数点也是不需要的。*/
 53 void trim()
 54 {
 55     int i,len,headzerocount,trailzerocount;
 56     headzerocount=trailzerocount=0;
 57     len=strlength(b);
 58     memmove(b+len-digit+1,b+len-digit,digit+1);
 59     b[len-digit]=‘.‘;
 60
 61     for(i=0;i<len+1;i++)
 62     {
 63         if(b[i]==‘0‘)
 64         {
 65             headzerocount++;
 66             continue;
 67         }
 68         break;
 69     }
 70     for(i=len;i>=0;i--)
 71     {
 72         if(b[i]==‘0‘)
 73         {
 74             trailzerocount++;
 75             continue;
 76         }
 77         break;
 78     }
 79     for(i=0;i<len-headzerocount-trailzerocount+1;i++)
 80     {
 81         c[i]=b[i+headzerocount];
 82     }
 83     if(c[len-headzerocount-trailzerocount]==‘.‘)
 84     {
 85         c[len-headzerocount-trailzerocount]=0;
 86     }
 87     else
 88     {
 89         c[len-headzerocount-trailzerocount+1]=0;
 90     }
 91 }
 92
 93 int main()
 94 {
 95     int i;
 96
 97     //mul("98999","98999");
 98
 99     while(scanf("%s %d",a,&p)!=EOF)
100     {
101         b[0]=‘1‘;
102         b[1]=0;
103         for(i=0;i<5;i++)
104         {
105             if(a[i]==‘.‘)
106             {
107                 memmove(a+i,a+i+1,6-i);
108                 digit=(6-i-1)*p;
109                 break;
110             }
111         }
112
113         for(i=0;i<p;i++)
114         {
115             mul(a,b);    //每次乘的结果都放在b里面
116         }
117
118         trim();
119         printf("%s\n",c);    //去掉0,加上小数点以后的值放在c里面
120     }
121     return 0;
122 }

总结一下,除了实现大数乘法和把小数点放到正确的位置上,还需要注意的细节有如下几点:

1.因为运算结果很有可能是比较长的字符串,所以需要注意不要让储存数据的数据结构有地址重叠的部分。

2.大数相乘时记得最后从后向前遍历一次把未进位的数位进位掉。

3.如果最终结果是个整数,那么小数点是没有用的,记得把它去掉。

时间: 2024-12-16 12:11:58

solution for POJ 1001的相关文章

POJ 1001 Exponentiation(JAVA,BigDecimal-&gt;String)

题目 计算实数a的n次方,具体输出格式看案例 import java.util.*; import java.math.*; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); BigDecimal a = BigDecimal.ONE; BigDecimal ans = BigDecimal.ONE; int n; while(in.hasNextBi

POJ 1001 Exponentiation 无限大数的指数乘法 题解

POJ做的非常好,本题就是要求一个无限位大的指数乘法结果. 要求基础:无限大数位相乘 额外要求:处理特殊情况的能力 -- 关键是考这个能力了. 所以本题的用例特别重要,再聪明的人也会疏忽某些用例的. 本题对程序健壮性的考查到达了变态级别了. 某人贴出的測试用例数据地址: http://poj.org/showmessage?message_id=76017 有了这些用例,几下调试就过了. 我关键漏了的用例: 000.10  1 000000  1 000.00  1 .00000  0 0000

POJ 1001 高精度

链接: http://poj.org/problem?id=1001 题意: 计算小数的幂,高精度 题解: 第一次用java ac,^-^ 代码: 1 import java.util.*; 2 import java.math.*; 3 4 public class Main { 5 public static void main(String args[]) { 6 Scanner cin = new Scanner(System.in); 7 while (cin.hasNext()) {

POJ 1001 Exponentiation(大数幂,还是Java大发好!需调用多个方法)

Exponentiation Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 156303   Accepted: 38063 Description Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the n

POJ 1001 解题报告 高精度大整数乘法模版

题目是POJ1001 Exponentiation  虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于错误的判断还不够严厉. 对边界情况的讨论其实应该是思维严密的表现,当然这并不能表明我写的一点错误都没有,只是多多分析一下还是很有好处的. #include <iostream> #include <fstream> #include <string> #include &l

POJ 1001 Exponentiation

Exponentiation Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 171995   Accepted: 41641 Description Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the n

POJ 1001 题解

题目大意是求一个实数R的N次方,此题第一次想到用快速幂做,后来发现快速幂只适用于整数计算,就没有采用.此题的突破点在于题目中给的R是一个固定长度的字符串,这就提示我们R可以看做字符串,读入以后提取小数点,并转化为一个整数计算,完成后的结果可以再用记录下的小数长度确定小数点的位置. 那么,输入的问题解决了,后来在写快速幂的时候发现最终的数据过大,没有办法用64位整数存储.就以为是高精快速幂.后来观察数据,发现指数数据范围较小,可以用高精度乘法解决这个问题.于是最终确定为使用高精乘解决这个问题. #

poj 1001 java大精度

import java.io.* ; import java.math.* ; import java.util.* ; import java.text.* ; public class Main { public static void main(String[] args) { Scanner cin=new Scanner (System.in) ; BigDecimal A; int B ; while(cin.hasNext()){ A=cin.nextBigDecimal() ;

POJ 1001 Exponentiation 模拟小数幂

模拟小数幂 小数点位 pos 非零末位 e 长度 len 只有三种情况 pos > len pos < e e < pos < len 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 int a[500], b[500], c[500]; 5 void Cal() 6 { 7 memset(c, 0, sizeof(c)); 8 for(int i = 0; i <