您的位置:首页 > 其它

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.。。。。。

上代码:

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: