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;
}
时间: 2024-08-03 23:34:57

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

[code3119]高精度练习之大整数开根

试题描述  给出一个正整数n,求n开根号后的整数部分的值.n的位数不超过1000位. 输入 读入一个不超过1000位的正整数n. 输出 输出所求答案 输入示例 17   输出示例 4 高精度开根:需要用的是手算开平方根的方法,我其实这个方法也不会,是临时到网上学习的 网上说的方法都挺详细的,我在这里就不详细说了,下面直接贴代码: 高精度模板需要用到高减高,高乘低,高加低. 1 #include<iostream> 2 #include<algorithm> 3 #include&l

VIjos 大整数(超级恶心的高精)

背景 很久很久以前,有个整数很大很囧 描述 一个k(1<=k<=80)位的十进制正整数N,就是所谓的大整数.请你设计程序,对于给出的某一个大整数N,找到满足p^3+p^2+3p<=n的p的最大值. 格式 输入格式 输入数据只有一行,是一个K位的大整数N,行首行未无多余空格 输出格式 输出第一行为你所找到的P最大值,行首行末别乱加东西 样例1 样例输入1 1000000000000001000000000000003000000000000001 Copy 样例输出1 1000000000

BZOJ 1213 HNOI2004 高精度开根 二分+高(Py)精(thon)度

题目大意:求n^(1/m) 一大早水个Python- - 直接开根尼玛过不去- - 需要二分- - m,n=int(raw_input()),int(raw_input()) l,r=0,1 while r**m<=n: l=r;r=r*2 while l+1<r: mid=(l+r)//2 if mid**m<=n: l=mid else: r=mid if r**m<=n: print r else: print l

整数平方根:整数开方及大整数开方解决方法

求整数N的开方,精度在0.001 二分法 若N大于1,则从[1, N]开始,low = 1, high = N, mid = low + (high - low) >> 1开始进行数值逼近 若N小于1,则从[N, 1]开始,low = 0, high = N, mid = low + (high - low) >> 1开始进行数值逼近 #include <stdio.h> #include <stdlib.h> #include <math.h>

大整数类BIGN的设计与实现 C++高精度模板

首先感谢刘汝佳所著的<算法竞赛入门经典>. 众所周知,C++中储存能力最大的unsigned long long 也是有着一个上限,如果我们想计算非常大的整数时,就不知所措了,所以,我写了一个高精度类,允许大整数的四则运算 这个类利用字符串进行输入输出,并利用数组进行储存与处理,通过模拟四则运算,可以计算很大的整数的加减乘除比大小. 贴上我的代码: #include<string> #include<iostream> #include<iosfwd> #i

COJ 1211 大整数开平方

手写求大整数开根号所得到的值,具体计算过程参考别人的资料,最后利用java的大整数得到答案 别人博客链接:http://www.cnblogs.com/Rinyo/archive/2012/12/16/2820450.html 1.举例 上式意为65536的开平方为256.手开方过程类似于除法计算.为了方便表述,以下仍称类似位置的数为“被除数”.“除数”.“商”. 以65536为例,其具体计算过程如下: Step1:将被开方数(为了形象,表述成“被除数”,此例中即为65536)从个位往高位每两位

大整数的加减乘除

多项式的加减乘除能够利用多项式的加减乘除进行运算,所以下面程序採用了多项式的加减乘除.多项式运算已经在<算法导论>第30章有简要的介绍,详细的请參考数学书. 大整数加法:(利用书上公式轻松得出) //多项式加法-大数加法 #include <iostream> #include <time.h> using namespace std; #define m1 4 #define m2 5 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数

模板 高精度大整数

#include<bits/stdc++.h> #define clr(x,y) memset((x),(y),sizeof(x)) using namespace std; typedef long long LL; const int MaxL=400; //大数长度 //大整数 //减法只能大减小 struct bign { int len, s[MaxL]; //构造函数 bign () { memset(s, 0, sizeof(s)); len = 1; } bign (int n

uva 424(Integer Inquiry)高精度大整数加法

这是一道很标准的大整数加法,我却wa了4次,没提交一次就查到一些细节问题,比如说我们考虑前导 0的问题,还有就是没有对输入数组处理, 使得他们每次输入时高位的置0,还有就是没考虑到最后相加后的进位, 这些问题一一改正之后,还是wa了,原来是因为,我把if语句中的==只写了一个...真坑啊,,,我就说怎么会 不过,明明写的对的,大数相加竟然还wa了四次,还有就是这道题最后不写换行也会wa...看来还是有必要从基础练起提高代码能力: 贴代码: #include<stdio.h> #include&