大数开根

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define DEPTH 10

typedef int BigInteger[10100];

int comp(const BigInteger a,const int c,const int d,const BigInteger b) //大数比较
{
    int i,t=0,O=-DEPTH*2;
    if(b[0]-a[0]<d&&c) return 1;
    for(i=b[0];i>d;i--)
    {
        t=t*DEPTH+a[i-d]*c-b[i];
        if(t>0) return 1;
        if(t<O) return 0;
    }
    for(i=d;i;i--)
    {
        t=t*DEPTH-b[i];
        if(t>0) return 1;
        if(t<O) return 0;
    }
    return t>0;
}

void sub(BigInteger a,const BigInteger b,const int c,const int d) //大数减
{
    int i,O=b[0]+d;
    for(i=1+d;i<=O;i++)
        if((a[i]-=b[i-d]*c)<0)
            a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH;
    for(;a[i]<0;a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH,i++);
    for(;!a[a[0]]&&a[0]>1;a[0]--);
}

void Sqrt(BigInteger b,BigInteger a) //开平方
{
    int h,l,m,i;
    memset((void*)b,0,sizeof(BigInteger));
    for(i= b[0]=(a[0]+1)>>1;i;sub(a,b,m,i-1),b[i]+=m,i--)
        for(h=DEPTH-1,l=0,b[i]=m=(h+l+1)>>1;h>l;b[i]=m=(h+l+1)>>1)
            if(comp(b,m,i-1,a)) h=m-1;
            else l = m;
    for(;!b[b[0]]&&b[0]>1;b[0]--);
    for (i = 1; i <= b[0]; b[i++] >>= 1);
}

char str[10100];
BigInteger a,b;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s",str);
        a[0]=strlen(str);
        for(int i=1; i<=a[0]; i++)
            a[i]=str[a[0]-i]-‘0‘;
        Sqrt(b,a);
        for(int i=b[0]; i>=1; i--)
            printf("%d",b[i]);
        printf("\n");
        if(t)
            puts("");
    }
    return 0;
}

http://blog.csdn.net/acdreamers/article/details/8885090http://blog.csdn.net/hondely/article/details/6939895
时间: 2024-10-03 13:46:17

大数开根的相关文章

平方开根 - 牛顿迭代(板子整理)

long long 范围内的开根 int Sqrt(int x) { if (x == 0) return 0; double last = 0; double res = 1; while (res != last) { last = res; res = (res + x / res) / 2; } return int(res); } 浮点数的开根 double fun(double x) { if (x == 0) return 0; double last = 0.0; double

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

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

[BZOJ3211]花神游历各国(线段树+区间开根)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3211 分析: 区间开根是没法区间合并的. 但是注意到10^9开根开个5次就变成1了…… 于是只要在每个区间额外维护个值b,b=1表示这段全部都是1了,不用修改了,b=2表示这段没有全部是1,还要修改 然后这样就行了

【BZOJ1213】高精度开根

python是坠吼的! 原题: 不贴原题,就是高精度开根,结果向下取整 首先二分答案,高精度嘛--python即可 二分右端点设为n会T掉,需要先倍增一个r,while(r **m <= n)  r *= 2 然后T掉了,代码如下,亮点自寻 1 m, n = input(), input() 2 l, r = 0, n 3 while r ** m < n: 4 r *= 2 5 6 while(l + 1 < r): 7 md = (l + r) >> 1 8 if(md

算法模板——线段树5(区间开根+区间求和)

实现功能——1:区间开根:2:区间求和(此模板以BZOJ3038为例) 作为一个非常规的线段树操作,其tag也比较特殊呵呵哒 1 var 2 i,j,k,l,m,n:longint; 3 a,b:array[0..500000] of int64; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end; 8 function min(x,y:longint):long

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 内

kb-07线段树-08--区间开根

1 /* 2 hdu-4027 3 题目:区间开根求和查询: 4 因为是开根,所以要更新的话就要更新到叶子节点.如果区间里全是1或是0的话就步用继续更新了,查询的时候正常查询: 5 */ 6 #include<iostream> 7 #include<cstring> 8 #include<cstdio> 9 #include<cmath> 10 #define ll long long 11 using namespace std; 12 struct N

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

【HNOI2004】【BZOJ1213】高精度开根

Description 晓华所在的工作组正在编写一套高精度科学计算的软件,一些简单的部分如高精度加减法.乘除法早已写完了,现在就剩下晓华所负责的部分:实数的高精度开m次根.因为一个有理数开根之后可能得到一个无理数,所以这项工作是有较大难度的.现在要做的只是这项工作的第一步:只对自然数进行开整数次根,求出它的一个非负根,并且不考虑结果的小数部分,只要求把结果截断取整即可.程序需要根据给定的输入,包括需要开根的次数,以及被开根的整数:计算出它的非负根取整后的结果. Input 共有两行,每行都有一个