1. 程式人生 > >【codevs3119】高精度開根號(二分答案)

【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<<'\n';
    */
    return 0;
}