zoukankan      html  css  js  c++  java
  • 北大ACM1001题Exponentiation(求高精度幂)

    从昨天开始训练ACM题目,每题尽量用C++和java编写,为了熟悉算法和java语言。

     题目是这样的:

    求高精度幂 Time Limit: 500MS Memory Limit: 10000K Total Submissions: 44697 Accepted: 10245

    Description

    对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。

    现在要你解决的问题是:对一个实数R( 0.0 < R < 99.999 ),要求写程序精确计算 R 的 n 次方(Rn),其中n 是整数并且 0 < n <= 25。 Input

    T输入包括多组 R 和 n。 R 的值占第 1 到第 6 列,n 的值占第 8 和第 9 列。 Output

    对于每组输入,要求输出一行,该行包含精确的 R 的 n 次方。输出需要去掉前导的 0 后不要的 0 。如果输出是整数,不要输出小数点。 Sample Input

    95.123 12 0.4321 20 5.1234 15 6.7592 9 98.999 10 1.0100 12

    Sample Output

    548815620517731830194541.899025343415715973535967221869852721

    .00000005148554641076956121994511276767154838481760200726351203835429763013462401

    43992025569.928573701266488041146654993318703707511666295476720493953024

    29448126.764121021618164430206909037173276672

    90429072743629540498.107596019456651774561044010001

    1.126825030131969720661201

    下面的代码是我自己编写的,由于网络原因,一直测试为waiting,先放着,哪天测试。

    C++:

    思路是这样的:由于C++里面没有像java里面的BigDecimal这样的类型,只能靠算法来实现,由于数据太大,那就用数组来装载数据,数组里面的每一个元素都不会超过9,这样首先申请一个空间为250的一维数组m[250]。然后里面只存放每次相乘得到的结果。用一个6元素大小的字符数组装底数,char r[6],r[0]=9,r[1]=5,r[2]=.,r[3]=1,r[4]=2,r[5]=3,现在就不要小数点,存放在int b[6](要进行处理),对于多出来的位置,则用-1表示,这样在存放在m中就可以容易识别。然后在m中,每一位(如9)分别乘以96123,得到一个大数,这个大数就采用模10和除以10分别放在9前面的位置里面。例如9*95123=856107,然后m中对应9的位置就放7,7前面的五位数就分别加0,1,6,5,8.如果想加超过9,则还要将进的1加到前面一位。最后就是:m[4]=7,m[5]=0,m[6]=1,m[7]=6,m[8]=5等等,这样每一位都乘了95123,并且也分别存在在m中,下一个循环就是对m中的每一位数据(存放在一个数组中的一个单元里)再乘以95123,重复上面的过程n次,最后m中的数据就是结果,打印的时候也要注意有没有小数点。不知道说清楚没,就这样吧。希望下次我来看的时候能记起来。

    代码:

      1 #include <iostream>
    2 using namespace std;
    3 int main()
    4 {
    5 char r[6]={'0'};//底数
    6 int n=1;//指数
    7 while(cin>>r>>n)
    8 {
    9 int m[250]={0};
    10 int b[6]={0};
    11 int i,j,m_i;
    12 int m_number=0,m_data=0;//小数点个数,每次相乘的数据
    13 for(i=0;i<6;i++)//找到小数点的位置
    14 {
    15 if(r[i]=='.')
    16 {
    17 m_i=i;
    18 break;
    19 }
    20 }
    21 if(i==6)//说明没有小数点
    22 {
    23 j=0;
    24 while(r[j]=='0')
    25 {
    26 r[j]='a';
    27 j++;
    28 }
    29 m_number=0;
    30 }
    31 else//说明有小数点
    32 {
    33 i=0;
    34 while(i<m_i&&r[i]=='0')//小数点之前前导0处理为-1
    35 {
    36 r[i]='a';
    37 i++;
    38 }
    39 i=5;
    40 while(i>m_i&&(!r[i]||r[i]=='0'))//小数点之后的后缀零处理
    41 {
    42 r[i]='a';//赋值为a
    43 i--;
    44 }
    45 for(i=5;i>=0;--i)
    46 {
    47 if(!r[i]||r[i]=='a')continue;
    48 if(r[i]=='.')break;
    49 m_number++;//判断有多少小数
    50 }
    51 }
    52 for(i=0,j=0;i<6;++i)
    53 {
    54 if(r[i]=='a')continue;
    55 if(r[i]=='.')continue;
    56 if(!r[i])continue;
    57 b[j]=(int)(r[i]-'0');//转成int的b
    58 j++;
    59 }
    60 while(j<6)
    61 {
    62 b[j]=-1;
    63 j++;
    64 }//b可以弄出实数来了
    65 for(i=0;i<6;++i)
    66 {
    67 if(b[i]==-1)continue;
    68 m_data=m_data*10+b[i];//相乘的大数
    69 }
    70 for(j=5,i=250-1;j>=0&&i>=0;--j)
    71 {
    72 if(b[j]==-1)continue;
    73 else
    74 {
    75 m[i]=b[j];//赋值给m
    76 i--;
    77 }
    78 }
    79 m_number=m_number*n;
    80 n--;
    81 while(n--&&i!=249)//如果出现输入都是0
    82 {
    83 for(j=i+1;j<250;j++)//有这么多位
    84 {
    85 int tem=m[j]*m_data;//每一位与数相乘
    86 m[j]=0;
    87 if(tem==0)m[j]=0;
    88 else
    89 {
    90 int t=j;
    91 while(tem/10!=0||tem%10!=0)
    92 {
    93 m[t]=m[t]+tem%10;//将每一位都分离出来存放在不同的单元
    94 int tt1=t;
    95 while(m[tt1]>9)//对超过9的处理
    96 {
    97 int tem2=m[tt1];
    98 m[tt1]=tem2%10;//得到这位的数据
    99 tt1--;
    100 m[tt1]=m[tt1]+tem2/10;//往前加进的位数
    101 }
    102 t--;
    103 tem=tem/10;
    104 }
    105 }
    106 }
    107 i=0;
    108 while(m[i]==0)i++;//找到m中第一个非零的位置
    109 i--;
    110 }
    111 i=0;
    112 while(i<250&&m[i]==0)
    113 i++;
    114 if(m_number==0)//对没有小数点的处理
    115 {
    116 if(i==250)cout<<0<<endl;
    117 else
    118 {
    119 for(;i<250;++i)cout<<m[i];
    120 cout<<endl;
    121 }
    122 }
    123 else//有小数点的处理
    124 {
    125 if(m_number>250-i)//250-i表示在i之前有i个零,有250-i个非零
    126 {//小数点超过相乘得到的实数,则补零
    127 cout<<".";
    128 while(m_number-->250-i)
    129 cout<<0;
    130 for(;i<250;i++)
    131 cout<<m[i];
    132 cout<<endl;
    133 }
    134 else
    135 {
    136 for(;i<250;++i)
    137 {
    138 if(m_number==250-i)cout<<".";//包含处理等于
    139 cout<<m[i];
    140 }
    141 cout<<endl;
    142 }
    143 }
    144 }
    145 return 0;
    146 }

    下面是用java编写:

        

     1 import java.io.*;
    2 import java.util.*;
    3 import java.math.BigDecimal;
    4
    5 public class Main
    6 {
    7 public static void main(String args[])throws Exception
    8 {
    9 Scanner cin=new Scanner(System.in);
    10 while(cin.hasNext())
    11 {
    12 BigDecimal r=cin.nextBigDecimal();
    13 int n=cin.nextInt();
    14 r=r.pow(n).stripTrailingZeros();//去掉小数点后面的零
    15 String m_string=r.toPlainString();//不带指数段的字符串表示形式
    16 if(m_string.charAt(0)=='0')
    17 m_string=m_string.substring(1);
    18 System.out.println(m_string);
    19 }
    20 }
    21 }

    OK,希望自己能坚持做ACM题目。

  • 相关阅读:
    树链剖分 (模板) 洛谷3384
    ST表 (模板) 洛谷3865
    IOI 2005 River (洛谷 3354)
    IOI 2005 River (洛谷 3354)
    poj1094 Sorting It All Out
    poj1094 Sorting It All Out
    spfa(模板)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    洛谷1850(NOIp2016) 换教室——期望dp
  • 原文地址:https://www.cnblogs.com/leewiki/p/2283911.html
Copyright © 2011-2022 走看看