POJ 1001——高精度快速幂
本题主要用到两个东西,一个是高精度,一个是快速幂。
虽然是浮点数的乘法,但是实际上可以转化为整数的乘法,然后再用高精度乘法,高精度算法本身不难,但是在没重载运算符的情况下使用数组还是挺麻烦的,不少地方的初始化都需要特别注意。
数组名在函数内部时,它的sizeof数组名获得的是数组本身的长度,而数组作为函数形参的时候,sizeof获得的是这个指针本身的长度,这一点特别坑,这会导致memset函数出现问题。
关于快速幂:
快速幂是一种快速求出数字的幂的方法,将指数写成二进制的形式,然后将底数自平方,每平方一次就从低到高对应着指数的二进制位,判断该位是否有效(是否为1),然后乘在结果上即可。
计算a^b的代码:
int res = 1;
while(b){
if(b%2) res*=a;// 该位是否有效
a*=a;// 下一位权重
b/=2;// 下一位指数(模2)
}
return res;
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 100001
void multi(int a[],int b[],int res[]){
for(int i=0;i<maxn;i++) res[i] = 0;
res[0] = a[0] + b[0] - 1;
for(int i=1;i<=a[0];i++)
for(int j=1;j<=b[0];j++){
res[i+j-1]+=a[i]*b[j];
res[i+j]+=res[i+j-1]/10;
res[i+j-1]%=10;
}
if(res[res[0]+1]) res[0]++;
return;
}
void power(int a[],int n,int res[]){
int r[maxn];
memset(r, 0, sizeof(r));
r[0] = 1;
r[1] = 1;
while(n){
if(n%2) {
multi(r, a, res);
memcpy(r, res, (res[0]+1)*sizeof(int));
}
multi(a, a, res);memcpy(a, res, (res[0]+1)*sizeof(int));
n/=2;
}
memcpy(res, r, (r[0]+1)*sizeof(int));
}
int main(){
char s[1001];
int a[maxn];
int n;
while (scanf("%s%d",s,&n)==2) {
int dotPos = 0;
int cnt = 0;
for(int i = (int)strlen(s)-1;i >= 0;i--){
if(s[i] == '.') dotPos = cnt;
else a[++cnt] = s[i] - '0';
}
a[0] = (int)strlen(s) - (dotPos?1:0);
// 去除后导0
if(dotPos){
reverse(a+1, a+a[0]+1);
while(!a[a[0]] && dotPos){
a[0]--;
dotPos--;
}
reverse(a+1, a+a[0]+1);
}
dotPos *= n;
while(!a[a[0]]){
a[0]--;
}
int res[maxn];
memset(res, 0, sizeof(res));
power(a, n, res);
dotPos=res[0]-dotPos;
if(dotPos<=0){// 加前导0
printf("%c",'.');
while (dotPos<0) {
printf("%d",0);
dotPos++;
}
for(int i=res[0];i>=1;i--){
printf("%d",res[i]);
}
printf("\n");
}
else{
for(int i=res[0];i>=1;i--){
if(dotPos+i==res[0]) {printf("%c",'.');printf("%d",res[i]);}
else printf("%d",res[i]);
}
printf("\n");
}
}
}
1284KB 0ms