已退役


私信TA

用户名:15893197790

访问量:14398

签 名:

努力学习,积极生活。

等  级
排  名 389
经  验 5119
参赛次数 0
文章发表 43
年  龄 0
在职情况 学生
学  校 南京大学
专  业 计算机科学与技术

  自我简介:

已退役。研究生方向为AI+软件工程,欢迎学术交流!

解题思路:本质就是求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 人评分

  评论区

  • «
  • »