zoukankan      html  css  js  c++  java
  • hdu 1063 Exponentiation代码及分析

        在看过我们学校前几届的大牛他的博客后,我决定也用Exponentiation来作为我的第一篇解题报告,不过我用的是hdu的Exponentiation。

       http://acm.hdu.edu.cn/showproblem.php?pid=1063

        之所以我用hdu的而不用poj 1001的题,是因为这个的技术含量相对较高。poj 1001的那题我依稀记得当时我用了半个小时AC了,但是我在hdu的acm step里面再次遇到它时却耗费了我将近两个小时来AC。其中一个原因是hdu出的数据太坑人了,明明说好的是含小数的100以内的数,但是在我WA后,我不断地修改,不断地参考别人的代码,最后才发现原来这里还有只是整数作为底数的数据。

        这个题目的没在高精度乘法里让我们用分治法处理作限制,因而只要普通的高精度乘法就能够完成任务了。这题相对较难的是小数点位置的确定,我没有像网上那些大神那般的高精度计算,反而我是用了比较慢的处理方法,从而保证结果的正确。就是这样,我在数据读入后做预处理(pre_process)和数据输出前的收尾工作(post_process)。因为数据量不是很大,这就足以让我有更多的时间减少中间计算的失误。

        下面就是我的代码,简单的说就是处理好数据立后就不断地调用高精度乘法,然后在数据输出前再次处理数据(加上小数点以及去掉没用的0)……

    View Code
      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #include<math.h>
      5 
      6 char base[10];//名称相对来说挺明确的了,应该不会有混乱的情况发生
      7 char *ans;
      8 int base_pow, point_pos;
      9 int sign_z;//这个要说明一下,因为我的代码是基于poj1001重写出来的,因而一开始没有判断整数货小数的标识符,所以就加了这个是否Z的标识
     10 
     11 void pre_process(void)//这是预处理,主要是用来判断输入的数是不是整数,以及观察小数点的位置,从而为后续工作做准备
     12 {
     13     int i;
     14     for(i=0; i<6; i++)
     15         if(base[i] == '.')break;//遇到小数点就停止,从而得出小数的位数
     16     if(i>=6)sign_z=0;//如果找不到小数点,说明输入的是整数
     17     else
     18     {
     19         sign_z=1;
     20         point_pos = (5-i)*base_pow;
     21         for(; i<5; i++)//这个是为了高精度乘法后处理的方便,把末尾的零都补上了
     22         {
     23             if(base[i+1])
     24                 base[i]=base[i+1];//从小数点之后的那位开始逐位移动
     25             else
     26                 base[i]='0';
     27         }
     28         base[5]=0;//收尾,防止越界
     29     }
     30 }
     31 char *multi(char *c_a, char *c_b)//高精度乘法,理论上可以移植到其他程序去
     32 {
     33     int i, j, k, l;
     34     int len_a=strlen(c_a);
     35     int len_b=strlen(c_b);
     36 
     37     int *a = (int *)malloc(len_a*sizeof(int));
     38     int *b = (int *)malloc(len_b*sizeof(int));
     39     int *sum = (int *)malloc((len_a+len_b) * sizeof(int));
     40     char *c_sum = (char *)malloc((len_a+len_b+2) * sizeof(char));//这里本应只需+1位,但为了添加小数点后输出的方便,那一位是留给小数点的
     41 
     42     memset(a, 0, len_a*sizeof(int));//这一部分都是用于初始化的
     43     memset(b, 0, len_b*sizeof(int));
     44     memset(sum, 0, (len_a+len_b)*sizeof(int));
     45 
     46     for(i=0; i<len_a; i++)a[i]=c_a[i]-'0';//转化字符数组为普通数组
     47     for(i=0; i<len_b; i++)b[i]=c_b[i]-'0';
     48 
     49     for(i=0; i<len_a; i++)//进行乘法运算,其实就是小学竖式乘法的原理无异
     50         for(j=0; j<len_b; j++)
     51             sum[i+j+1]+=a[i]*b[j];
     52     c_sum[len_a+len_b]=c_sum[len_a+len_b+1]=0;//也是收尾用的
     53     for(i=len_a+len_b-1; i>0; i--)//这是把大于9的部分进位,加到高位中去
     54     {
     55         sum[i-1]+=sum[i]/10;
     56         c_sum[i]=sum[i]%10+'0';
     57     }
     58     c_sum[0]=sum[0]+'0';//转化回字符数组
     59 
     60     free(a);//用完了就要扔,不应该囤积垃圾
     61     free(b);
     62     free(sum);
     63 
     64     return c_sum;/*if(c_sum[0]!='0')return c_sum;else return &c_sum[1];*/
     65 }
     66 char *post_process(void)//这是收尾的处理,在这里把小数点加上去,以便输出时一并输出
     67 {
     68     int pre, post;
     69     int len=strlen(ans);
     70     int i;
     71 if(sign_z){//如果有小数点的话……
     72     for(i=0; i<point_pos; i++)//顺序寻找小数点应放的位置
     73         ans[len-i]=ans[len-i-1];
     74     ans[len-point_pos]='.';//加上小数点
     75 
     76     post=len;
     77 
     78     while(ans[post]=='0'||ans[post]=='.')//这是用来删除后缀0的
     79         if(ans[post]=='.')
     80         {
     81             ans[post]=0;
     82             break;
     83         }
     84         else ans[post--]=0;
     85 }
     86     pre=0;
     87     while(ans[pre]=='0')pre++;//这是用来删除前缀0的
     88 
     89 }
     90 int main()
     91 {
     92     int i;
     93 
     94     while(scanf("%s%d"base, &base_pow)!=EOF)//输入要求,做完那10题基本输入输出,我彻底的动了…………
     95     {
     96         pre_process();
     97         ans=base;
     98         for(i=1; i<base_pow; i++)//暴力的不断乘
     99             ans=multi(ans, base);
    100         printf("%s\n", post_process());//终于可以直接一次过输出了……
    101     }
    102     return 0;
    103 }
    104 
    105 
    106 End

    written by Lyon(beginner)

  • 相关阅读:
    黄聪:解决Web部署 svg/woff/woff2字体 404错误
    黄聪:C#中HtmlAgilityPack判断是否包含或不包含指定的属性或值
    黄聪:GeckoFX如何引用jquery文件并执行自定义JS
    黄聪:css3实现图片划过一束光闪过效果(图片光影掠过效果)
    黄聪:C#带cookie模拟登录百度
    黄聪:如何为IIS增加svg和woff等字体格式的MIME
    黄聪:微信支付错误两个问题的解决:curl出错,错误码:60
    黄聪:《跟黄聪学WordPress插件开发》
    黄聪:GeckoWebBrowser多窗口独立cookie
    黄聪:远程连接mysql数据库注意事项记录(远程连接慢skip-name-resolve)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_1063_Lyon.html
Copyright © 2011-2022 走看看