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题目。

  • 相关阅读:
    替换Srun3000解决掉网问题
    了解Equals所发生的事情
    WPF自定义TextBox及ScrollViewer
    自制多类编码转换工具
    .NET4.5之自制多LRC转SRT小工具
    JAVA_list总结
    记一次线程Timer导致的线程安全问题修正
    JAVA_匿名内部类
    JAVA_map总结
    JAVA_闭包
  • 原文地址:https://www.cnblogs.com/leewiki/p/2283911.html
Copyright © 2011-2022 走看看