UVa 10023 - Square root 大数开方
2014-06-19 15:58
387 查看
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.。。。。。
上代码:
View Code
题目大意,给一个数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.。。。。。
上代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MOD = 2; const int D_MOD = 100; const int MAXN = 1000 + 5; int n; char str[MAXN]; int getInt(char *str, int len) { int res = 0; for(int i = 0; i < len; ++ i) res = res * 10 + (str[i] - '0'); return res; } class BigNumber { public: int intLen; int decimal[MAXN]; BigNumber() { this->intLen = 1; memset(this->decimal, 0, sizeof(this->decimal)); } BigNumber(char *str) { //初始化 this->intLen = 1; int intLen = (int)strlen(str); this->intLen = (intLen + MOD - 1) / MOD; memset(this->decimal, 0, sizeof(this->decimal)); if(intLen & 1) { this->decimal[this->intLen - 1] = getInt(str, 1); ++str; } else { this->decimal[this->intLen - 1] = getInt(str, 2); str += 2; } for(int i = this->intLen - 2; i >= 0; -- i, str += 2) this->decimal[i] = getInt(str, 2); } bool operator > (const BigNumber &x) const { if(this->intLen == x.intLen) for(int i = x.intLen - 1; i >= 0; -- i) if(this->decimal[i] != x.decimal[i]) return this->decimal[i] > x.decimal[i]; return this->intLen > x.intLen; } bool operator == (const BigNumber &x) const { if(this->intLen == x.intLen) { for(int i = 0; i < x.intLen; ++ i) if(this->decimal[i] != x.decimal[i]) return false; return true; } return (this->intLen == x.intLen); } //加上一个小于D_MOD的数 BigNumber operator + (int x) const { int tt; BigNumber bg; bg.intLen = this->intLen; for(int i = 0; i < this->intLen; ++ i) { tt = this->decimal[i] + x; bg.decimal[i] = tt % D_MOD; x = tt / D_MOD; } if(x) bg.decimal[bg.intLen++] = x; return bg; } //保证了差为正数时才可调用 BigNumber operator - (const BigNumber & x) const { BigNumber bg; bg.intLen = this->intLen; for(int i = 0; i < bg.intLen; ++ i) bg.decimal[i] = this->decimal[i] - x.decimal[i]; for(int i = 0; i < bg.intLen - 1; ++ i) if(bg.decimal[i] < 0) { --bg.decimal[i + 1]; bg.decimal[i] += D_MOD; } for(int i = bg.intLen - 1; i > 0; -- i) if(bg.decimal[i] == 0) --bg.intLen; else break; return bg; } //乘一个小于D_MOD的数 BigNumber operator * (int x) const { BigNumber bg; if(x == 0) return bg; int tt, temp = 0; bg.intLen = this->intLen; for(int i = 0; i < this->intLen; ++ i) { tt = this->decimal[i] * x + temp; bg.decimal[i] = tt % D_MOD; temp = tt / D_MOD; } while(temp) { bg.decimal[bg.intLen++] = temp % D_MOD; temp /= D_MOD; } return bg; } //移位操作,乘以D_MOD void MoveOneStep() { for(int i = this->intLen - 1; i >= 0; -- i) this->decimal[i + 1] = this->decimal[i]; if(this->decimal[this->intLen] != 0) ++this->intLen; } void OutPut() { printf("%d", this->decimal[this->intLen - 1]); for(int i = this->intLen - 2; i >= 0; -- i) printf("%02d", this->decimal[i]); putchar('\n'); } }; int Find_b(const BigNumber &a, const BigNumber &r) { BigNumber temp; for(int b = 1; b < 10; ++ b) { temp = a * (20 * b) + b * b; if(temp > r) return b - 1; else if(r == temp) return b; } return 9; } void Sqrt(const BigNumber &x) { BigNumber a, r; int b, tLen = x.intLen - 1; a.decimal[0] = (int)sqrt(x.decimal[tLen] + 0.5); r.decimal[0] = x.decimal[tLen--] - a.decimal[a.intLen - 1] * a.decimal[a.intLen - 1]; while(tLen >= 0) { r.MoveOneStep(); r.decimal[0] = x.decimal[tLen--]; b = Find_b(a, r); r = r - (a * (20 * b) + b * b); a = a * 10 + b; } a.OutPut(); } int main() { int T; scanf("%d\n", &T); while(T--) { gets(str); BigNumber x(str); Sqrt(x); getchar(); if(T) putchar('\n'); } return 0; }
View Code
相关文章推荐
- Square root - UVa 10023 大数开方
- UVa 10023 - Square root 大数开方
- uva 10023 - Square root(手动开方)
- UVA - 10023 - Square root (模拟手算开方)
- UVA 10023 Square root(高精度开方)
- uva 10494(大数加减乘除取余一条龙模板代码) uva 10023 (大数开方)
- UVa 10023 - Square root
- UVa 10023 - Square root
- UVA 10023 Square root
- UVA 10023 - Square root(手算平方根)
- UVA - 10023 Square root
- UVa 10023 - Square root
- UVA 10023 Square root
- UVA 10023 Square root
- UVA 10023 - Square root(手算开根)
- UVa 10023 Square root (高精度&开平方公式)
- uva 10023 Square root
- uva10023 手算开方的方法
- 10023 - Square root
- UVA11520(p31)----Fill the Square