codevs3119 高精度练习之大整数开根

3119 高精度练习之大整数开根
 
题目描述 Description
给出一个正整数n,求n开根号后的整数部分的值。n的位数不超过1000位。

输入描述 Input Description
读入一个不超过1000位的正整数n。

输出描述 Output Description
输出所求答案

样例输入 Sample Input
17

样例输出 Sample Output
4

数据范围及提示 Data Size & Hint

n为不超过1000位的正整数 满足  1<=n <10^1000

算法分析:有手工迭代算法,

http://wenku.baidu.com/view/a80e1b81bceb19e8b8f6bada.html?re=view

容易想到的算法:二分,

例如394500,找到可能的左端点600,可能的右端点700,然后通过高精度大小判断,高精度*高精度,高精度除单精度得到答案。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(I,start,end) for(int I=start;I<=end;I++)
#define PER(I,start,end) for(int I=start;I>=end;I--)
using namespace std;
long long tmp[1100];
struct bigNumber{//????? 
   int len;
   long long num[1100];
   
   inline bool operator >(const bigNumber T)const{
       if(len<T.len)return false;
       if(len>T.len)return true;
       PER(ii,len,1){
           if(num[ii]<T.num[ii])return false;
           if(num[ii]>T.num[ii])return true;
       }
       return false;
   }
   inline bool operator ==(const bigNumber T)const{
       if(len!=T.len)return false;
       PER(ii,len,1){
           if(num[ii]!=T.num[ii])return false;
       }
       return true;
   }
   

}a;
inline bigNumber operator +(const bigNumber A,const bigNumber B){
    bigNumber C;
    memset(C.num,0,sizeof(C.num));
    C.len=max(A.len,B.len);
    REP(ii,1,C.len)
        C.num[ii]=A.num[ii]+B.num[ii];
    REP(ii,1,C.len){
        C.num[ii+1]+=C.num[ii]/10;
        C.num[ii]%=10;
    }
    while(C.num[C.len+1]){
        C.len++;
        C.num[C.len+1]+=C.num[C.len]/10;
        C.num[C.len]%=10;
    }
    return C;
}

inline bigNumber operator *(const bigNumber A,const bigNumber B){
    bigNumber C;
    memset(C.num,0,sizeof(C.num));
    C.len=A.len+B.len-1;
    REP(ii,1,A.len)
        REP(jj,1,B.len)
            C.num[ii+jj-1]+=A.num[ii]*B.num[jj];
    REP(ii,1,C.len){
        C.num[ii+1]+=C.num[ii]/10;
        C.num[ii]%=10;
    }
    while(C.num[C.len+1]){
        C.len++;
        C.num[C.len+1]+=C.num[C.len]/10;
        C.num[C.len]%=10;
    }
    return C;
}

inline bigNumber operator /(const bigNumber A,const long long B){//高精度/单精度 
    long long T=0ll;
    bigNumber C;
    memset(C.num,0ll,sizeof(C.num));
    C.len=A.len;
    PER(ii,A.len,1){	    
        T=(T*10+A.num[ii]);
		C.num[ii]=T/B;
		T=T%B;
		}
	while(C.len>1&&C.num[C.len]==0)C.len--;   
    return C;
}
inline void print(const bigNumber T){
    if(T.len==0){
        printf("0");
    return;
    }
    PER(ii,T.len,1)
        printf("%lld",T.num[ii]);
    printf("\n");
}


inline void scan(bigNumber& T){
    memset(T.num,0,sizeof(T.num));
    T.len=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    ch=getchar();
    if(ch=='0'){
        ch=getchar();
        if(ch<'0'||ch>'9')
        return;
    }
    while(ch=='0')
    ch=getchar();
    while(ch>='0'&&ch<='9'){
        T.num[++T.len]=ch-'0';
        ch=getchar();
    }
    if(T.len==1&&T.num[1]==0){
        T.len=0;
        return;
    }
    REP(ii,1,T.len>>1)
        swap(T.num[ii],T.num[T.len-ii+1]);
}


int main()
{ 
  int alen,al,ar,ahead;
  
  bigNumber left,right,mid,sqr;  
  scan(a);
  if (a.len&1)ahead=a.num[a.len];//找出最高位数字,1-99 
  else ahead=a.num[a.len]*10+a.num[a.len-1];
  for  (int i=1;i<=9;i++){ //找出最高位对应的平方根 
  	if(i*i<=ahead&&ahead<(i+1)*(i+1))
  	  al=i;
  }
  memset(left.num,0,sizeof(left.num)); 
  memset(right.num,0,sizeof(right.num)); 
  left.len=right.len=(a.len-1)/2+1;//长度折半找到开根的左右端点。
  left.num[left.len]=al;
  if (al<9) right.num[right.len]=al+1;
  else{
  	right.len++;
  	right.num[right.len]=1;
  } 
  
  while( true){
    mid=left+right;
    mid=mid/2;
    if((mid==left)||(mid==right))break;  
  	sqr=mid*mid; 
  	if (sqr>a)//在左侧 
  		right=mid;
	else left=mid; 	
  }
 print(mid);
 return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值