首页 > 代码库 > codevs 3119 高精度练习之大整数开根 (各种高精+压位)

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/*codevs 3119 高精度练习之大整数开根 (各种高精+压位)二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in  结果:AC    内存使用量:  256kB     时间使用量:  0ms     测试点#2.in  结果:AC    内存使用量:  256kB     时间使用量:  1ms     测试点#3.in  结果:AC    内存使用量:  256kB     时间使用量:  0ms     测试点#4.in  结果:AC    内存使用量:  256kB     时间使用量:  10ms     测试点#5.in  结果:AC    内存使用量:  256kB     时间使用量:  56ms */#include<cstdio>#include<cstring>#include<cmath>#define maxn 1010#define ll long long #define bas 100000000#define mem(a,b) for(ll i=0;i<=len;i++)a[i]=b[i];#define mes(a)   for(ll i=0;i<=len;i++)a[i]=0;using namespace std;ll len,a[maxn],l[maxn],r[maxn],mid[maxn],ans[maxn],x[maxn];char s[maxn];ll max(ll x,ll y){    return x>y?x:y;}void plu(ll a[maxn],ll b[maxn]){    ll c[maxn];mes(c);    c[0]=max(a[0],b[0]);    for(int i=1;i<=c[0];i++){        c[i]+=a[i]+b[i];        if(c[i]>=bas){            c[i+1]++;c[i]%=bas;        }    }    if(c[c[0]+1])c[0]++;    mem(mid,c);}void Plu(ll a[maxn],ll b){    ll p=1,c[maxn];mes(c);    mem(c,a);c[p]++;    while(c[p]>=bas){        c[p]%=bas;c[p+1]++;p++;    }    if(c[c[0]+1])c[0]++;    mem(l,c);}void miu(ll a[maxn],ll b){    ll p=1,c[maxn];mes(c);    mem(c,a);c[p]--;    while(c[p]<0){        c[p]+=bas;c[p+1]--;p++;    }    if(c[c[0]]==0)c[0]--;    mem(r,c);}void mul(ll a[maxn],ll b[maxn],ll c[maxn]){    for(int i=1;i<=a[0];i++){        for(int j=1;j<=b[0];j++){            c[i+j-1]+=a[i]*b[j];            if(c[i+j-1]>=bas){                c[i+j]+=c[i+j-1]/bas;                c[i+j-1]%=bas;            }        }        ll len=i+b[0];        while(c[len]>=bas){            c[len+1]+=c[len]/bas;            c[len]%=bas;len++;        }    }    for(int i=a[0]+b[0];i>=1;i--)        if(c[i]){            c[0]=i;break;        }}void div(ll a[maxn],ll b){    ll c[maxn];mes(c);    for(int i=a[0];i>=1;i--){        c[i]=a[i+1]%b*bas+a[i];        c[i]=c[i]/b;    }    for(int i=a[0];i>=1;i--)        if(c[i]){            c[0]=i;break;        }    mem(a,c);}bool cmp(ll a[maxn],ll b[maxn]){    if(a[0]>b[0])return 0;    if(a[0]<b[0])return 1;    for(ll i=a[0];i>=1;i--){        if(a[i]>b[i])return 0;        if(a[i]<b[i])return 1;    }    return 1;}bool Judge(){    memset(x,0,sizeof(x));    mul(mid,mid,x);    return cmp(x,a);}int main(){    scanf("%s",s);    a[0]=strlen(s);len=a[0];    for(int i=1;i<=a[0];i++)        a[i]=s[a[0]-i]-0;    for(int i=1;i<=len;i+=8)        x[++x[0]]=a[i+7]*10000000+a[i+6]*1000000+a[i+5]*100000+        a[i+4]*10000+a[i+3]*1000+a[i+2]*100+a[i+1]*10+a[i];    mem(a,x);    mem(r,a);r[0]=a[0]/2+1;    while(cmp(l,r)){        plu(l,r);        div(mid,2);        if(Judge()){            mem(ans,mid);            Plu(mid,1);        }        else miu(mid,1);    }    printf("%lld",ans[ans[0]]);    for(ll i=ans[0]-1;i>=1;i--)        printf("%08lld",ans[i]);    return 0;}

 

codevs 3119 高精度练习之大整数开根 (各种高精+压位)