今天看到这道题了 poj1001 题目地址是http://bailian.openjudge.cn/practice/1001/

英文看得懂,可是算法不明白,所以转别人的文章,留着给学生看看:乔高建(高精度

  • 解题思路

    这道题属于高精度乘法运算,要求输入一个实数R一个指数N,求实数R的N次方,由于R有5个数位,而N又特别大,因此用C++自带的数据类型放不下.
    解题思路是通过数组储存每次乘积结果和底数的每一位数,按照乘法上下算式的方法,计算底数乘数数组每一位与临时结果数组的每一位的乘积,(因为算术运算中是从数的后面往前算的,这里存储数时要先倒序,输出时再颠倒过来,)然后偏移相加,判断得出的临时结果数组的每一位是否大于9,通过除法和取模实现进位和取余.至此得出一个有很多无效数位的结果数组(很多无效的0).
    最后判断结果数组的每一位是否为0,先输出小数点前面的数,后输出小数点后面的数,最终得出乘法结果.
    这个题目实际上考的是高精度乘法,高精度的其他运算和这个差不多,原理都是一样的.

  • Description

    Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.
    This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

  • Input

    The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

  • Output

    The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.

  • 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

  • Hint

    If you don't know how to determine wheather encounted the end of input:
    s is a string and n is an integer

  • SourceCode

#include<iostream>
#include<cstring> using namespace std; int main()
{
string r; //底数
int n,dianwei; //指数,小数点位置
const int len=200; //数位长度
short result[len],jieguo[len],chengshu[6]; //最终结果,临时结果,底数乘数
while(cin>>r>>n)
{
//初始化
for(int i=0;i<len;++i) jieguo[i]=result[i]=0;
for(int i=0;i<6;++i) chengshu[i]=0;
dianwei=0;
//得到底数小数点位置
size_t pos = r.find('.');
//如果底数中有小数点 获取小数点后面有多少位数
if(pos!=string::npos) dianwei=(5-pos)*n; //把底数中所有不是小数点的数字挑出来转换为int并赋给最终结果,临时结果,底数乘数 得到的是3个5位前后颠倒的数组 之所以颠倒是因为乘法是从后往前乘的
for(int i=5,j=0;i>=0;--i)
{
if(r[i]!='.')
{
jieguo[j]=result[j]=chengshu[j]=r[i]-'0';
++j;
}
} //当指数大于1时 进行以下运算 等于1时跳过这段程序直接输出
while(n>=2)
{
--n;
//初始化最终结果数组
for(int i=0;i<len;++i) result[i]=0; for(int i=0;i<5;++i) //从底数乘数的每一位
{
//底数乘数每位数和临时结果每位数相乘的临时变量
int temp;
for(int j=0;j<len;++j) //乘以临时结果的每一位
{
//如果底数乘数某一位是0 没必要乘下去了 跳出当前循环
if(chengshu[i]==0) break;
temp=chengshu[i]*jieguo[j];
//i+j实现乘法相加时的移位
result[i+j]+=temp;
//++t遍历所有结果数组中大于9的数 用除法和取模实现进位和余数
for(int t=i+j;result[t]>9;++t)
{
result[t+1]+=result[t]/10;
result[t]=result[t]%10;
}
}
}
//把一次乘法后的结果赋给临时结果来进行下次乘方
for(int i=0;i<len;++i) jieguo[i]=result[i];
} //获取最终结果从后数第一个不为0的数作为第一个数的标志位 之所以从后数 是因为之前颠倒的数要颠倒回来了
int firstindex=-1;
for(int i=len;i>=dianwei;--i)
{
if(result[i]>0)
{
firstindex=i;
break;
}
}
//获取 最终结果从前数第一个不为0的数作为最后一个数的标志位
int lastindex=-1;
for(int i=0;i<dianwei;++i)
{
if(result[i]>0)
{
lastindex=i;
break;
}
} //如果最终结果数组中不全是0 倒序输出结果数组中小数点前面的数
if(firstindex!=-1)
{
while(firstindex>=dianwei)
{
cout<<result[firstindex];
--firstindex;
}
}
//如果最终结果数组中不全是0 倒序输出结果数组中小数点后面的数
if(lastindex!=-1)
{
cout<<'.';
--dianwei;
while(dianwei>=lastindex)
{
cout<<result[dianwei];
--dianwei;
}
} cout<<endl;
}
}

#附录:

一.高精度数的存储

1.字符串输入

#include <iostream>
#include <cstring>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i;
string s1;
cin>>s1;//数s1
memset(a,0,sizeof(a)); //数组清0
a[0]=s1.length(); //位数
for(i=1;i<=a[0];i++)
{
a[i]=s1[a[0]-i]-'0';//将字符转为数字并倒序存储.
}
return 0;
}

2.直接读入

#include <iostream>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i,s,key;
cin>>key;//数key
memset(a,0,sizeof(a)); //数组清0
i=0;//第0位
while(key) //当key大于0
{
a[++i]=key%10;//取第i位的数
key=key/10;
}
a[0]=i; //共i位数
return 0;
}

3.直接初始化(用a[]存储)

  • 初始化为0: memset(a,0,sizeof(a));
  • 初始化为1: memset(a,0,sizeof(a));a[0]=1;a[1]=1;

以下程序都只写函数,不写完整程序,所有高精度数存储都满足上述约定。

二.高精度数比较

int compare(int a[],int b[])   //比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0
{
int i;
if (a[0]>b[0]) return 1;//a的位数大于b则a比b大
if (a[0]<b[0]) return -1;//a的位数小于b则a比b小
for(i=a[0];i>0;i--) //从高位到低位比较
{
if (a[i]>b[i]) return 1;
if (a[i]<b[i]) return -1;
}
return 0;//各位都相等则两数相等。
}

三、高精度加法

int plus(int a[],int b[]) //计算a=a+b
{int i,k;
k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位数最大的一个的位数
for(i=1;i<=k;i++)
{
a[i+1]+=(a[i]+b[i])/10; //若有进位,则先进位
a[i]=(a[i]+b[i])%10; //计算当前位数字,注意:这条语句与上一条不能交换。
}
if(a[k+1]>0)
{
a[0]=k+1; //修正新的a的位数(a+b最多只能的一个进位)
}
else
{
a[0]=k;
}
return 0;
}

四、高精度减法

int gminus(int a[],int b[]);//计算a=a-b,返加符号位0:正数 1:负数
{
int flag,i
flag=compare(a,b); //调用比较函数判断大小
if (falg==0)//相等
{
memset(a,0,sizeof(a));return 0; //若a=b,则a=0,也可在return前加一句a[0]=1,表示是 1位数0
}
if(flag==1) //大于
{
for(i=1;i<=a[0];i++)
{
if(a[i]<b[i]){ a[i+1]--;a[i]+=10;} //若不够减则向上借一位
a[i]=a[i]-b[i];
}
while(a[a[0]]==0) a[0]--; //修正a的位数
return 0;
}
if (flag==-1)//小于 则用a=b-a,返回-1
{
for(i=1;i<=b[0];i++)
{
if(b[i]<a[i]){ b[i+1]--;b[i]+=10; //若不够减则向上借一位
}
a[i]=b[i]-a[i];}
a[0]=b[0];
while(a[a[0]]==0) a[0]--; //修正a的位数
return -1;
}
}

五、高精度乘法(高精度乘单精度数,单精度数是指通常的整型数)

int multi1(int a[],long  key) //a=a*key,key是单精度数
{
int i,k;
if (key==0){memset(a,0,sizeof(a));a[0]=1;return 0;} //单独处理key=0
for(i=1;i<=a[0];i++)
{
a[i]=a[i]*key;//先每位乘起来
}
for(i=1;i<=a[0];i++)
{
a[i+1]+=a[i]/10;a[i]%=10; //进位
}
//注意上一语句退出时i=a[0]+1
while(a[i]>0)
{
a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++]; //继续处理超过原a[0]位数的进位,修正a的位数
}
return 0;
}
 
分类: ACM

高精度POJ1001的更多相关文章

  1. POJ-1001 Exponentiation 高精度算法

    题目链接:https://cn.vjudge.net/problem/POJ-1001 以前写过一个高精度乘法,但是没有小数点,实现起来也没什么难得, 现在把代码都般过来,等会把旧电脑弄一弄,暂时就不 ...

  2. C# 高精度求幂 poj1001

    高精度求幂 public static char[] exponentiation(string a,int r) { ]; string b = ""; string c = a ...

  3. poj1001(高精度)

                                                               Exponentiation Time Limit: 500MS   Memory ...

  4. 求高精度幂(poj1001)

    Description Problems involving the computation of exact values of very large magnitude and precision ...

  5. CSharpGL(28)得到高精度可定制字形贴图的极简方法

    CSharpGL(28)得到高精度可定制字形贴图的极简方法 回顾 以前我用SharpFont实现了解析TTF文件从而获取字形贴图的功能,并最终实现了用OpenGL渲染文字. 使用SharpFont,美 ...

  6. 递推+高精度 UVA 10497 Sweet Child Makes Trouble(可爱的孩子惹麻烦)

    题目链接 题意: n个物品全部乱序排列(都不在原来的位置)的方案数. 思路: dp[i]表示i个物品都乱序排序的方案数,所以状态转移方程.考虑i-1个物品乱序,放入第i个物品一定要和i-1个的其中一个 ...

  7. [Template]高精度模板

    重新写一下高精度模板(不要问我为什么) 自认为代码风格比较漂亮(雾 如果有更好的写法欢迎赐教 封装结构体big B是压位用的进制,W是每位长度 size表示长度,d[]就是保存的数字,倒着保存,从1开 ...

  8. Code[VS] 3123 高精度练习之超大整数乘法

    FFT 做 高精度乘法 #include <bits/stdc++.h> ); struct complex { double a, b; inline complex( , ) { a ...

  9. Java 高精度数字

    BigInteger // 高精度整数 BigDecimal //高精度小数  小数位数不受限制

随机推荐

  1. 《JAVA并发编程实战》示例程序 第三章

    3.1 可见性 程序清单3-1 在没有同步的情况下共享变量(不要这么做) /** * 主线程和读线程都将访问共享变量:ready 和 number * 结果可能 * 1. 主线程先运行完,读线程后运行 ...

  2. easyui 菜单树搜索

    //树形菜单搜索方法    function searchTree(treeObj,parentNode,searchCon){        var children;        for(var ...

  3. Convolutional Pose Machines(理解)

    0 - 背景 人体姿态识别存在遮挡以及关键点不清晰等主要挑战,然而,人体的关键点之间由于人体结构而具有相互关系,利用容易识别的关键点来指导难以识别关键点的检测,是提高关键点检测的一个思路.本文通过提出 ...

  4. 函数节流和函数防抖JavaScript实现

    函数节流 function throttle(fn, delay = 1000) { let Running = false; return function () { if (Running) { ...

  5. Linux查看日志工具

    ⒈journalctl journalctl是Centos7才有的工具用于systemd统一管理所有unit的启动日志,只用一个journalctl命令就可以查看所有的日志(包括内核日志和应用日志), ...

  6. gojs常用API-画布定义

    持续更新中 基础画布定义API画布初始位置 initialContentAlignment: go.Spot.Center,画布位置,定义后就不能拖动画布了,画布位置交由gojs管理 contentA ...

  7. java学习笔记08-switch case语句

    switch是一种选择语句,可以通过匹配某个条件,来执行某块代码 switch(expression){ case value: break;//可选 default://可选 //语句 } swit ...

  8. 010_TCP queue的研究

    先来回顾下三次握手里面涉及到的问题:1. 当 client 通过 connect 向 server 发出 SYN 包时,client 会维护一个 socket 等待队列,而 server 会维护一个 ...

  9. openssl 1.1.1 reference

    openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...

  10. CSS动画:animation、transition、transform、translate

    https://blog.csdn.net/px01ih8/article/details/80780470 一.区分容易混淆的几个属性和值 先区分一下css中的几个属性:animation(动画). ...