解题思路:本质就是求sqrt(n)*sqrt(m),时间复杂度是O(maxlen^3),maxlen是数的位数。使用普通高精显然超时,那就压8位为1位,大大减小系数。
开long long防越界(一般压位超过4位就要开long long)
注意事项:
参考代码:
#include<bits/stdc++.h>//这题转化为对m开根号(向下取整)*对n开根号(向下取整)
//所以这一题考的就是高精度开根号,高精度乘法
using namespace std;
typedef long long ll;
#define maxlen 130
char str[1010];
ll n[maxlen],m[maxlen],l[maxlen],r[maxlen],mid1[maxlen],mid2[maxlen],tmp1[maxlen],ans[maxlen];
int cmp(ll *a,ll *b){//a<b返回-1,a=b返回0,a>b返回1
for(int i=maxlen-1;i>=0;i--){
if(a[i]<b[i])return -1;
if(a[i]>b[i])return 1;
}
return 0;
}
void add1(ll *a,int x){//高精度数加一个普通整数,a=a+x
a[0]+=x;
int i=0;
while(a[i]>99999999){
a[i+1]+=a[i]/100000000;
a[i]%=100000000;
i++;
}
}
void add2(ll *a,ll *b,ll *c){//c=a+b+1,这里加1是为了实现l+r+1
for(int i=0;i<maxlen;i++){
c[i]=a[i]+b[i];
}
c[0]+=1;
for(int i=0;i<maxlen-1;i++){
c[i+1]+=c[i]/100000000;
c[i]%=100000000;
}
}
void sub(ll *a,int x){//高精度数减一个普通整数,a=a-x
a[0]-=1;
int i=0;
while(a[i]<0){
a[i]+=100000000;
a[i+1]-=1;
i++;
}
}
void divtwo(ll *a){//a=a/2,向下取整
for(int i=maxlen-1;i>=1;i--){
if(a[i]&1){//如果a[i]是奇数
a[i]>>=1;
a[i-1]+=100000000;
}
else{
a[i]>>=1;
}
}
a[0]>>=1;
}
void mul(ll *a,ll *b,ll *c){//c=a*b
memset(c,0,1640);//sizeof(long long int)*205
for(int i=0;i<maxlen;i++){
for(int j=0;j<maxlen;j++){
if(i+j+1>maxlen-1)break;
c[i+j]+=a[i]*b[j];
c[i+j+1]+=c[i+j]/100000000;
c[i+j]%=100000000;
}
}
}
void copy(ll *a,ll *b){//a=b
for(int i=0;i<maxlen;i++){
a[i]=b[i];
}
}
void bigsqrt(ll *a,ll *mid){//对a开根号,mid=根号a
int cmpans;//mid*mid与a比较的结果
while(cmp(l,r)!=0){//当l<r时
add2(l,r,mid);
divtwo(mid);//l<mid<=r
mul(mid,mid,tmp1);
cmpans=cmp(tmp1,a);
if(cmpans==0)return;
else if(cmpans==-1){
copy(l,mid);//l=mid
}
else{
copy(r,mid);
sub(r,1);//r=mid-1
}
}
copy(mid,l);
}
void print(ll *aa){//输出
bool flag=0;//记录是否能输出
for(int i=maxlen-1;i>=0;i--){
if(!flag){//如果不能
if(aa[i]){
flag=1;//找到第一个不是0的位,可以输出了
printf("%lld",aa[i]);//第一个不能前补0
continue;
}
}
else printf("%08lld",aa[i]);//输出,不用空格或换行
}
}
int main(){
scanf("%s",str);
int lenstr=strlen(str);
for(int i=0;i<lenstr;i++){//每8位数字作为高精度的一位,这样高精度数组最大长度就是125了
n[(lenstr-1-i)/8]*=10;
n[(lenstr-1-i)/8]+=str[i]-'0';
}
scanf("%s",str);
lenstr=strlen(str);
for(int i=0;i<lenstr;i++){
m[(lenstr-1-i)/8]*=10;
m[(lenstr-1-i)/8]+=str[i]-'0';
}
copy(r,n);
bigsqrt(n,mid1);
copy(r,m);memset(l,0,sizeof(l));
bigsqrt(m,mid2);
mul(mid1,mid2,ans);
print(ans);
system("pause");
return 0;
}
0.0分
1 人评分
C语言训练-大、小写问题 (C语言代码)浏览:792 |
C语言程序设计教程(第三版)课后习题8.8 (C语言代码)浏览:895 |
【偶数求和】 (C++代码)浏览:744 |
C语言程序设计教程(第三版)课后习题4.9 (Java代码)浏览:629 |
1063题 初学者,求帮忙看下,不知道哪错了浏览:239 |
ACM俱乐部密码浏览:948 |
Tom数 (Java代码)浏览:617 |
P1003 (Java代码)浏览:782 |
Manchester- 求之N内的素数浏览:1510 |
Manchester- A+B for Input-Output Practice (II)浏览:1365 |