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

Posted 一入OI深似海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 高精度练习之大整数开根 (各种高精+压位)的主要内容,如果未能解决你的问题,请参考以下文章

CodeVS 3123 高精度练习之超大整数乘法

CODEVS3115高精度练习之减法

18.2.28 codevs3115 高精度练习之减法

18.2.28 codevs3115 高精度练习之乘法

3118 高精度练习之除法

Code[VS] 3123 高精度练习之超大整数乘法