OJ_1001

来源:互联网 发布:画蜡烛图 软件 编辑:程序博客网 时间:2024/05/16 19:52
原题连接:http://poj.org/problem?id=1001&lang=zh-CN
 
求高精度幂
Time Limit: 500MS Memory Limit: 10000KTotal Submissions: 106968 Accepted: 26029

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 120.4321 205.1234 156.7592  998.999 101.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721.0000000514855464107695612199451127676715483848176020072635120383542976301346240143992025569.92857370126648804114665499331870370751166629547672049395302429448126.76412102161816443020690903717327667290429072743629540498.1075960194566517745610440100011.126825030131969720661201

Source

East Central North America 1988

Translator

北京大学程序设计实习,Xie Di
 
 
============================================================================
真TMD佩服CSDN,如此XX用户的意愿。自己上传的资源自己都不能删除,真是服大发了!如果代码
写的有问题难道还非得误导那些下载的朋友们!下面的代码已经放在新浪爱问资料共享,地址
http://iask.sina.com.cn/u/ish,没有上传工程文件,你可以随便用哪个版本的VC建一个就可以。
 
工程目录如下:
 
 
注:目前程序性能还达不到要求500MS,正在调试中。。。
/**************************************************************************************************///basecls.h/*运算实现的基类,不同的操作可以从此处派生出一个实现类*/#include <string>using namespace std;virtual class clsBaseAcl{public:    virtual std::string Acl(const std::string strOp1, const std::string strOp2) = 0;}; /*************************************************************************************************///acl.h#include "basecls.h"class clsAdd:public clsBaseAcl{public:    std::string Acl(const std::string strOp1, const std::string strOp2);};class clsSub:public clsBaseAcl{public:    std::string Acl(const std::string strOp1, const std::string strOp2);};class clsMultiply:public clsBaseAcl{public:    std::string Acl(const std::string strOp1, const std::string strOp2); std::string AclEx(const std::string strOp1, const std::string strOp2);};std::string strAcl(const std::string strOp1, const std::string strOp2, int nBeforeOrAfter, int* pCarry);/*返回R的N次方*/std::string strRetRN(const std::string R, const short n);void RemodePreZero(string& str);void RemodeZero(string& str);/*******************************************************************************************///acl.cpp #include "acl.h"char spliter = '.';std::string clsAdd::Acl(const std::string strOp1, const std::string strOp2){ int carry = 0;    string str1(strOp1);    string str2(strOp2); string strBefore1; string strBefore2; string strAfter1; string strAfter2; string strOut1; string strOut2;    int npos1 = str1.find(spliter);    if(string::npos == npos1)    {        str1 += ".0";  npos1 = str1.length() - 2;    }    int npos2 = str2.find(spliter);    if(string::npos == npos2)    {        str2 += ".0";  npos2 = str2.length() - 2;    }     strBefore1 = str1.substr(0, npos1); strBefore2 = str2.substr(0, npos2); strAfter1 = str1.substr(npos1 + 1, str1.length() - npos1 - 1); strAfter2 = str2.substr(npos2 + 1, str2.length() - npos2 - 1); strOut1 = strAcl(strAfter1, strAfter2, 0, &carry); strOut2 = strAcl(strBefore1, strBefore2, 1, &carry); strOut1 =  strOut2 + "." + strOut1;  //如果和的第0位还需要进位在加结果加1 if (1 == carry) {  strOut1 = "1" + strOut1; }    return strOut1;}std::string clsSub::Acl(const std::string strOp1, const std::string strOp2){    //return strOp1 + strOp2;    return "sub";}std::string clsMultiply::Acl(const std::string strOp1, const std::string strOp2){ clsAdd instAdd; string out; string retInt; string retDot; string strDot; int nInt = 0; int nDot = 0; int offset = 0; string s1(strOp1); int pos1 = strOp1.find(spliter); if (pos1 == string::npos) {        s1 = s1 + ".0"; } int pos = strOp2.find(spliter); if (pos != string::npos) {  int nLastZero = strOp2.find_first_not_of('0', pos + 1);  if (nLastZero != string::npos)  {   offset = nLastZero - pos;   nDot = atoi(strOp2.substr(pos + 1, strOp2.length() -pos - 1).c_str());   retDot = s1;   for (int j = 1; j < nDot; ++j)   {    retDot = instAdd.Acl(retDot, s1);   }     int nDotPos = retDot.find(spliter);   if(string::npos != nDotPos)   {    if (nDotPos > offset)    {     //20.5                 retDot = retDot.substr(0, nDotPos-1) + "." + retDot.substr(nDotPos-1, retDot.length() - nDotPos+1);     int nLastDotPos = retDot.find_last_of(".");                 if(string::npos != nLastDotPos)     {                     retDot = retDot.substr(0, nLastDotPos) + retDot.substr(nLastDotPos + 1, retDot.length() - nLastDotPos - 1);         retDot = "0" + retDot;     }    }    else    {     retDot = retDot.substr(0, nDotPos) + retDot.substr(nDotPos + 1, retDot.length() - nDotPos - 1);     string addzero(offset -nDotPos, '0');     retDot = "0." + addzero + retDot;    }     }  }  else  {      retDot = "0.0";  } } nInt = atoi(strOp2.substr(0, pos).c_str()); retInt = s1; for (int i = 1; i < nInt; ++i) {        retInt = instAdd.Acl(retInt, s1); }    return instAdd.Acl(retInt, retDot);}std::string clsMultiply::AclEx(const std::string strOp1, const std::string strOp2){ clsAdd instAdd; string out; int nDot1 = 0; int nDot2 = 0; int N2 = 0; int offset = 0; string s1(strOp1); int pos1 = strOp1.find(spliter); if (pos1 != string::npos) {  nDot1 = s1.length() - pos1 - 1;  s1 = s1.substr(0, pos1) + s1.substr(pos1 + 1, s1.length() - pos1 - 1); //去掉小数点 } string s2(strOp2); int pos2 = strOp2.find(spliter); if (pos2 != string::npos) {  nDot2 = s2.length() - pos2 - 1;  s2 = s2.substr(0, pos2) + s2.substr(pos2 + 1, s2.length() - pos2 - 1); } N2 = atoi(s2.c_str());    RemodePreZero(s1); out = s1; for (int i = 1; i < N2; ++i) {        out = instAdd.Acl(out, s1); } RemodeZero(out); //加入小数点 offset = nDot1 + nDot2; if (offset > 0) {  if (offset < out.length())  {   out = out.substr(0, out.length() - offset) + "." + out.substr(out.length() - offset, offset);  }  else  {      string sz(offset - out.length(), '0');      out = sz + out;      out = out.substr(0, out.length() - offset) + "." + out.substr(out.length() - offset, offset);  } } RemodeZero(out); if (0 == out.find(spliter)) {        out = "0" + out; }    return (out);}std::string strAcl(const std::string strOp1, const std::string strOp2, int nBeforeOrAfter, int* pCarry){    int dif = 0; int nStart = 0; int preCarry = 0; string str1; string str2; int tmp;    int curr; string strOut; str1 = strOp1; str2 = strOp2; if(strOp1.length() < strOp2.length()) {  str1 = strOp2;  str2 = strOp1; } nStart = str1.length() - 1; dif = str1.length() - str2.length(); string strAddZero(dif, '0'); if (1 == nBeforeOrAfter) {        //小数点之前,在数字前面补0  str2 = strAddZero + str2; }  else {  //小数点之后,在数字后面补0  str2 = str2 + strAddZero; } preCarry = *pCarry; while(nStart >= 0)    {        tmp = (str1[nStart]-'0') + (str2[nStart]-'0');        tmp += preCarry; //当前数字+上一位的进位        if(tmp >= 10)        {            curr = tmp%10;            preCarry = 1;        }        else        {            curr = tmp;            preCarry = 0;        }        nStart--;  char p[32] = {0};  sprintf(p, "%d", curr);  string s = p;  strOut = s + strOut;    } *pCarry = preCarry; return strOut;}std::string strRetRN(const std::string R, const short n){    string strOut; clsMultiply multi;    if( R.length() <= 0) {     return "para error"; }  if((n <= 0) || (n > 25)) {     return "para error"; } strOut = R; for(int i = 1; i < n; ++i) {     strOut = multi.AclEx(strOut, R); } return strOut;}//去掉前导0void RemodePreZero(string& str){ if (str.length() <= 0 ) {  return; } int dpos = str.find(spliter); if (string::npos == dpos) {     //本身没有小数点%     int pos = str.find_first_not_of('0');  if (pos > 0)  {   str = str.substr(pos, str.length() - pos);  } } else {//   int pos = str.find_first_not_of('0', dpos + 1);//   if ((pos > dpos) && (string::npos != pos))//   {//    str = str.substr(dpos - 1, str.length() - pos);//   }  }}//去掉多余的0void RemodeZero(string& str){ int nDotPos = -1; if (str.length() <= 0 ) {  return; } //如果小数点后全是0则去掉小数点后的0 int pos = str.find(spliter); if (string::npos != pos) {  int nFirstNotZero = -1;        nFirstNotZero = str.find_last_not_of('0'); //小数点后最后一个不是0的字符位置  if (nFirstNotZero == pos)  {    //走到这里说明小数点后都是0,去掉这些0和小数点    str = str.substr(0, pos);  }  else if(nFirstNotZero > pos)  {             str = str.substr(0, nFirstNotZero+1);  } } }/*********************************************************************************************///main.cpp #include <iostream>#include "acl.h"#include <cassert>using namespace std;clsAdd add;clsSub sub;clsMultiply multi;string a = "0.4321";string b = "12";string c = "00700";string out;//163.47 + 27.532 =191.002int main(){    //cout << "Hello world!" << endl; //out = add.Acl(a,b); RemodePreZero(a); RemodeZero(a); RemodePreZero(b); RemodeZero(b); //out = multi.AclEx(a,b); //assert("16" == out); out = strRetRN(a,20); //cout << out << endl;    //cout << sub.Acl(a,b)<< endl;    //cout << multi.Acl(a,b)<< endl;    return 0;}/************************************************************************************/