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 高精度练习之大整数开根 (各种高精+压位)的主要内容,如果未能解决你的问题,请参考以下文章