zoukankan      html  css  js  c++  java
  • 【codevs3119】高精度开根号(二分答案)

    problem

    高精度开根号

    • 输入一个数
    • 求平方根

    solution

    • 二分答案,如果mid*mid>原数就去找更小的,反之找更大的。
    • 精度小于二忽略不计?
    • 用到高精加,高精乘,加低精,除低精,比较大小这几个。

    放弃调试,明天重写。
    mmp

    codes1(更快的AC版本

    //二分答案
    #include<iostream>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn = 1010;
    int a[maxn], l[maxn], r[maxn], m[maxn], t[maxn];
    //m=l+r>>1
    void mid(){
        //m = l;
        memcpy(m,l,sizeof(l));
        //m += r;
        m[0] = r[0]+1;
        for(int i = 1; i <= r[0]; i++){
            m[i] += r[i];
            if(m[i]>=10){
                m[i] %= 10;
                m[i+1]++;
            }
        }
        while(m[0]>1 && m[m[0]]==0)m[0]--;
        //m /= 2;
        for(int i = m[0]; i >= 1; i--){
            if(i > 1)m[i-1]+=m[i]%2*10;
            m[i] /= 2;
        }
        while(m[0]>1 && m[m[0]]==0)m[0]--;
    }
    //return m*m>a;
    bool C(){
        //t = 0;
        memset(t,0,sizeof(t));
        //t = m*m;
        for(int i = 1; i <= m[0]; i++)
            for(int j = 1; j <= m[0]; j++)
                t[i+j-1] += m[i]*m[j];
        t[0] = m[0]*2;
        for(int i = 1; i <= t[0]; i++){//处理进位
            t[i+1] += t[i]/10;
            t[i] %= 10;
        }
        while(t[0]>1 && t[t[0]]==0)t[0]--;
        //return t>a;
        if(t[0] != a[0])return t[0]>a[0];
        for(int i = t[0]; i >= 1; i--)
            if(t[i]!=a[i])return t[i]>a[i];
        return 0;
    }
    
    int main(){
        //输入
        string s;  cin>>s;
        a[0] = s.size();
        for(int i = 1; i <= a[0]; i++)a[i] = s[a[0]-i]-'0';
        //二分
        l[0] = 1;
        r[0] = a[0]/2+2;
        r[r[0]] = 1;
        for(int i = 1; i <= 2000; i++){
            mid();  //m=l+r>>1;
            if(C())memcpy(r,m,sizeof(m));//r=m;
            else memcpy(l,m,sizeof(m));//l=m;
        }
        //输出
        for(int i = l[0]; i >= 1; i--)cout<<l[i];
        return 0;
    }
    

    code2(更容易读懂被TLE一个点的版本

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    using namespace std;
    const int maxn = 2010;
    struct Bigint{ int len, num[maxn]; };
    
    //return a+b;
    Bigint add(Bigint a, Bigint b){
        Bigint ans;  memset(ans.num,0,sizeof(ans.num));
        ans.len = max(a.len,b.len)+1;
        for(int i = 1; i <= ans.len; i++){
            ans.num[i] += a.num[i]+b.num[i];
            ans.num[i+1] += ans.num[i]/10;
            ans.num[i] %= 10;
        }
        while(ans.len>1 && ans.num[ans.len]==0)ans.len--;
        return ans;
    }
    //return (a+b)/2;
    Bigint avg(Bigint a, Bigint b){
        Bigint ans;  memset(ans.num,0,sizeof(ans.num));
        ans = add(a,b);
        //copy from
        for(int i=ans.len;i>=2;i--){
            ans.num[i-1]+=( ans.num[i]%2)*10; 
    
            ans.num[i]/=2;
        }
        ans.num[1] /= 2;
        if(ans.num[ans.len]==0)ans.len--;
        return ans;
    }
    //return a+2;
    Bigint plustwo(Bigint x){
        x.num[1] += 2;
        for(int i = 1; i <= x.len; i++){
            x.num[i+1] += x.num[i]/10;
            x.num[i] %= 10;
        }
        if(x.num[x.len+1]>0)x.len++;
        return x;
    }
    
    //return a*b;
    Bigint times(Bigint a, Bigint b){
        Bigint ans;  memset(ans.num,0,sizeof(ans.num));
        ans.len = a.len+b.len+1;
        for(int i = 1; i <= a.len; i++)
            for(int j = 1; j <= b.len; j++)
                ans.num[i+j-1] += a.num[i]*b.num[j];
        for(int i = 1; i <= ans.len; i++){
            ans.num[i+1] += ans.num[i]/10;
            ans.num[i] %= 10;
        }
        while(ans.len>1 && ans.num[ans.len]==0)ans.len--;
        return ans;
    }
    
    //return a<=b;
    bool over(Bigint a, Bigint b){
        if(a.len != b.len)return a.len < b.len;
        for(int i = a.len; i >= 1; i--)
            if(a.num[i] != b.num[i])return a.num[i]<b.num[i];
        return true;
    }
    
    
    Bigint l, r, mid, tmp;
    int main(){
        ios::sync_with_stdio(false);
        string s;  cin>>s;
        tmp.len = s.size();
        for(int i = 1; i <= tmp.len; i++)
            tmp.num[i] += s[tmp.len-i]-'0';
        
        l.len = 1, l.num[1] = 3; r = tmp;
        do{
            mid = avg(l,r);
            if(!over(times(mid,mid),tmp))r = mid;
            else l = mid;
        }while(over(plustwo(l),r)); //l+2<=r;
        /*
        for(int i = 1; i <= 1500; i++){
            mid = avg(l,r);
            if(!over(times(mid,mid),tmp))r = mid;
            else l = mid;
        }
        */
        for(int i = l.len; i >= 1; i--)
            cout<<l.num[i];
        /*
        mid = times(l,r);
        for(int i = mid.len; i >= 1; i--)
            cout<<mid.num[i];  cout<<'
    ';
        */
        return 0;
    }
    
  • 相关阅读:
    【React Native】使用react-native-wechat 进行微信好友、微信朋友圈进行分享
    【React Native】在网页中打开Android应用程序
    【React Native】错误提示: 在React开发中,我们可能经常会遇到这个一个警告: Can't perform a React state update on an unmounted component.
    【Swift】上传图片到腾讯云(生成token,上传)
    【React Native】集成声网Agora语音通讯
    【React Native】在React Native项目中使用rollbar-react-native记录
    【iOS】上传图片到七牛过程(生成Token,上传)
    【React Native】同步获取本地缓存键值对
    React Native之持久化存储(AsyncStorage、react-native-storage)的使用
    【React Native】手写Alert弹窗(单按钮,两个按钮)
  • 原文地址:https://www.cnblogs.com/gwj1314/p/10200079.html
Copyright © 2011-2022 走看看