首页 > 代码库 > [code3119]高精度练习之大整数开根

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

试题描述
 给出一个正整数n,求n开根号后的整数部分的值。n的位数不超过1000位。
输入
读入一个不超过1000位的正整数n。
输出
输出所求答案
输入示例
17  
输出示例
4

高精度开根:需要用的是手算开平方根的方法,我其实这个方法也不会,是临时到网上学习的

网上说的方法都挺详细的,我在这里就不详细说了,下面直接贴代码:

高精度模板需要用到高减高,高乘低,高加低。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<queue>
  6 #include<cstdio>
  7 using namespace std;
  8 typedef long long LL;
  9 inline int read()
 10 {
 11     int x=0,f=1;char c=getchar();
 12     while(!isdigit(c)){if(c==-)f=-1;c=getchar();}
 13     while(isdigit(c)){x=x*10+c-0;c=getchar();}
 14     return x*f;
 15 }
 16 const int maxn=1010;
 17 struct data
 18 {
 19     int l,v[maxn];
 20     data(){l=1;memset(v,0,sizeof(v));}
 21     data operator = (const data& s)
 22     {
 23         l=s.l;memset(v,0,sizeof(v));
 24         for(int i=1;i<=l;i++)v[i]=s.v[i];
 25         return *this;
 26     }
 27     data operator = (const int& s)
 28     {
 29         l=1;v[1]=s;
 30         while(v[l]>9)v[l+1]+=v[l]/10,v[l]%=10,l++;
 31         return *this;
 32     }
 33     data operator - (const data& s)
 34     {
 35         data c;c.l=l;
 36         for(int i=1;i<=c.l;i++)c.v[i]=v[i];
 37         for(int i=1;i<=c.l;i++)c.v[i]-=s.v[i];
 38         for(int i=1;i<c.l;i++)if(c.v[i]<0)c.v[i]+=10,c.v[i+1]--;
 39         while(!c.v[c.l])c.l--;
 40         return c;
 41     }
 42     data operator * (const int& s)
 43     {
 44         data c;c.l=l;
 45         for(int i=1;i<=c.l;i++)c.v[i]=v[i]*s;
 46         for(int i=1;i<c.l;i++)if(c.v[i]>9)c.v[i+1]+=(c.v[i])/10,c.v[i]%=10;
 47         while(c.v[c.l]>9)c.v[c.l+1]+=(c.v[c.l])/10,c.v[c.l]%=10,c.l++;
 48         return c;
 49     }
 50     data operator + (const int& s)
 51     {
 52         data c=*this;
 53         c.v[1]+=s;int i=1;
 54         while(c.v[i]>9)c.v[i+1]+=c.v[i]/10,c.v[i]%=10,i++;
 55         c.l=max(c.l,i);
 56         return c;
 57     }
 58     bool operator <= (const data& t)const 
 59     {
 60         if(l!=t.l)return l<t.l;
 61         for(int i=l;i;i--)if(v[i]!=t.v[i])return v[i]<t.v[i];
 62         return 1;
 63     }
 64 }a;
 65 int num[510];
 66 void scan(data &s)
 67 {
 68     char ch[maxn];
 69     scanf("%s",ch+1);s.l=strlen(ch+1);
 70     for(int i=1;i<=s.l;i++)s.v[i]=ch[s.l-i+1]-0; 
 71     return;
 72 } 
 73 void print(data s){for(int i=s.l;i;i--)printf("%d",s.v[i]);cout<<endl;}
 74 void init(data s)//将这个数从个位起,向左每两位分一节(例如65536变成6,55,36)
 75 {
 76     if(s.l%2)
 77     {
 78         num[0]=s.v[s.l];
 79         for(int i=2;i<=s.l;i+=2)num[i/2]=s.v[s.l-i+1]*10+s.v[s.l-i]; 
 80     }
 81     else for(int i=1;i<=s.l;i+=2)num[i/2]=s.v[s.l-i+1]*10+s.v[s.l-i];
 82     return;
 83 } 
 84 data Sqrt(data s)
 85 {
 86     data ans,t,q,p;
 87     ans=0;t=0;
 88     int len= s.l%2 ? s.l/2+1 : s.l/2;//划分块的数量 
 89     for(int i=0;i<len;i++)
 90     {
 91         t=(t*100)+num[i];
 92         p=ans*20;ans=ans*10;//这里的ans要提前乘以10,如果下面的循环一次都没进去的话,ans就不会更新了 
 93         for(int j=9;j>=0;j--)
 94         {
 95             q=(p+j)*j;
 96             if(q<=t)
 97             {
 98                 ans=ans+j;
 99                 t=t-q;
100                 break;
101             }
102         }
103     }    
104     return ans;
105 }
106 int main()
107 {
108     scan(a);
109     init(a);
110     print(Sqrt(a));
111     return 0;
112 }

 

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