UVa 10023 - Square root 大数开方

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=964


题目大意,给一个数y(1 <= y <= 10^1000),求 y 的开方,题目保证了y 是一个完全平方数,并且没有前导零或者空格,输入数据每个隔一行,输出数据每个隔一行。


大数开方主要是三种方法,二分,牛顿迭代,手算开方,我写的是手算开方的,调试了半天终于可以正常地算出结果了,那时候没有注意到输出要有空行,而且最后一个数据后不能有空行,结果WA了两天。。。为什么不显示PE,差点WA得哭了。


手算开方的原理是利用(10a + b)(10a + b)= 100 a^2 + 20ab + b^2,

先把一个大整数从最低位开始分解成两个一节的。 eg. 12,34,56,78,90

①首先先看最前面一节,小于等于12的一个最大的平方数是9,先取a = 3,此时余数是3,将下一节加入余数,得到r = 3,34

②接下来求最大的 b 使得 20ab + b^2 <= 334, 这里先将a 代进去,得到b = 5,此时余数是 9

③此时需要将a 用 10a + b 取代,所以这时候a = 35,讲下一节加入r ,r = 9,56

接着不断重复重复②和③这两个步骤。

这边顺便再写两步,此时再去找最大的 b 使得 20ab + b^2 <= 956,将a = 35代入,求得 b = 1, 然后r = 2,55,然后 a = 351,将后一节加入r, r = 2,55,78.。。。。。


上代码:

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int MOD = 2;
  7 const int D_MOD = 100;
  8 const int MAXN = 1000 + 5;
  9 
 10 int n;
 11 char str[MAXN];
 12 
 13 int getInt(char *str, int len)
 14 {
 15     int res = 0;
 16 
 17     for(int i = 0; i < len; ++ i)
 18         res = res * 10 + (str[i] - '0');
 19 
 20     return res;
 21 }
 22 
 23 class BigNumber
 24 {
 25 public:
 26     int intLen;
 27     int decimal[MAXN];
 28 
 29     BigNumber()
 30     {
 31         this->intLen = 1;
 32         memset(this->decimal, 0, sizeof(this->decimal));
 33     }
 34 
 35     BigNumber(char *str)
 36     {
 37         //初始化
 38         this->intLen = 1;
 39         int intLen = (int)strlen(str);
 40         this->intLen = (intLen + MOD - 1) / MOD;
 41         memset(this->decimal, 0, sizeof(this->decimal));
 42 
 43         if(intLen & 1)
 44         {
 45             this->decimal[this->intLen - 1] = getInt(str, 1);
 46             ++str;
 47         }
 48         else
 49         {
 50             this->decimal[this->intLen - 1] = getInt(str, 2);
 51             str += 2;
 52         }
 53 
 54         for(int i = this->intLen - 2; i >= 0; -- i, str += 2)
 55             this->decimal[i] = getInt(str, 2);
 56     }
 57 
 58     bool operator > (const BigNumber &x) const
 59     {
 60         if(this->intLen == x.intLen)
 61             for(int i = x.intLen - 1; i >= 0; -- i)
 62                 if(this->decimal[i] != x.decimal[i])
 63                     return this->decimal[i] > x.decimal[i];
 64 
 65         return this->intLen > x.intLen;
 66     }
 67 
 68     bool operator == (const BigNumber &x) const
 69     {
 70         if(this->intLen == x.intLen)
 71         {
 72             for(int i = 0; i < x.intLen; ++ i)
 73                 if(this->decimal[i] != x.decimal[i])
 74                     return false;
 75 
 76             return true;
 77         }
 78 
 79         return (this->intLen == x.intLen);
 80     }
 81 
 82     //加上一个小于D_MOD的数
 83     BigNumber operator + (int x) const
 84     {
 85         int tt;
 86         BigNumber bg;
 87         bg.intLen = this->intLen;
 88 
 89         for(int i = 0; i < this->intLen; ++ i)
 90         {
 91             tt = this->decimal[i] + x;
 92             bg.decimal[i] = tt % D_MOD;
 93             x = tt / D_MOD;
 94         }
 95 
 96         if(x)
 97             bg.decimal[bg.intLen++] = x;
 98 
 99         return bg;
100     }
101 
102     //保证了差为正数时才可调用
103     BigNumber operator - (const BigNumber & x) const
104     {
105         BigNumber bg;
106         bg.intLen = this->intLen;
107 
108         for(int i = 0; i < bg.intLen; ++ i)
109             bg.decimal[i] = this->decimal[i] - x.decimal[i];
110 
111         for(int i = 0; i < bg.intLen - 1; ++ i)
112             if(bg.decimal[i] < 0)
113             {
114                 --bg.decimal[i + 1];
115                 bg.decimal[i] += D_MOD;
116             }
117 
118         for(int i = bg.intLen - 1; i > 0; -- i)
119             if(bg.decimal[i] == 0)
120                 --bg.intLen;
121             else
122                 break;
123 
124         return bg;
125     }
126 
127     //乘一个小于D_MOD的数
128     BigNumber operator * (int x) const
129     {
130         BigNumber bg;
131 
132         if(x == 0)
133             return bg;
134 
135         int tt, temp = 0;
136         bg.intLen = this->intLen;
137 
138         for(int i = 0; i < this->intLen; ++ i)
139         {
140             tt = this->decimal[i] * x + temp;
141             bg.decimal[i] = tt % D_MOD;
142             temp = tt / D_MOD;
143         }
144 
145         while(temp)
146         {
147             bg.decimal[bg.intLen++] = temp % D_MOD;
148             temp /= D_MOD;
149         }
150 
151         return bg;
152     }
153 
154     //移位操作,乘以D_MOD
155     void MoveOneStep()
156     {
157         for(int i = this->intLen - 1; i >= 0; -- i)
158             this->decimal[i + 1] = this->decimal[i];
159 
160         if(this->decimal[this->intLen] != 0)
161             ++this->intLen;
162     }
163 
164     void OutPut()
165     {
166         printf("%d", this->decimal[this->intLen - 1]);
167 
168         for(int i = this->intLen - 2; i >= 0; -- i)
169             printf("%02d", this->decimal[i]);
170 
171         putchar('\n');
172     }
173 };
174 
175 int Find_b(const BigNumber &a, const BigNumber &r)
176 {
177     BigNumber temp;
178 
179     for(int b = 1; b < 10; ++ b)
180     {
181         temp = a * (20 * b) + b * b;
182 
183         if(temp > r)
184             return b - 1;
185         else if(r == temp)
186             return b;
187     }
188 
189     return 9;
190 }
191 
192 void Sqrt(const BigNumber &x)
193 {
194     BigNumber a, r;
195     int b, tLen = x.intLen - 1;
196     a.decimal[0] = (int)sqrt(x.decimal[tLen] + 0.5);
197     r.decimal[0] = x.decimal[tLen--] - a.decimal[a.intLen - 1] * a.decimal[a.intLen - 1];
198 
199     while(tLen >= 0)
200     {
201         r.MoveOneStep();
202         r.decimal[0] = x.decimal[tLen--];
203         b = Find_b(a, r);
204         r = r - (a * (20 * b) + b * b);
205         a = a * 10 + b;
206     }
207 
208     a.OutPut();
209 }
210 
211 int main()
212 {
213     int T;
214     scanf("%d\n", &T);
215 
216     while(T--)
217     {
218         gets(str);
219         BigNumber x(str);
220         Sqrt(x);
221         getchar();
222 
223         if(T)
224             putchar('\n');
225     }
226 
227     return 0;
228 }
View Code

 


 

posted @ 2014-06-19 15:58  Tank..  阅读(428)  评论(0编辑  收藏  举报