手动求开根
work(a,x)
{
现在要算根号(a)
a1 = a/100; a2 = a % 100;
令y满足 sqr(y)<=a1 && sqr(y+1)>a1
假设当前为填x;
则我们要求sqr(y*10+x) <= a && sqr(y*10+x+1) >a
sqr(y*10+x) = 100*sqr(y) + 20*y*x + sqr(x)
= 100*sqr(y) + x*(20*y+x);
于是我们就可以递归算.出(y)
从9~0枚举x
使得x*(20*y+x)<= a-sqr(y)*100 && (x+1)*(20*y+x)>a-sqr(y)*100;
得出x.
}
递归算work(a1,x);
如此反复就可以得出答案。。
我下面的程序采用递推。从前面算到后面。work函数的意思也与上述表述不同。
在算高精的时候没有将数组倒序,也就是说我的第0位为最高位。
/*Author : Lit
*Data : 3.15 2011
*Mehod :手动开根号的方法。。
*http://hi.baidu.com/yali79/blog/item/290416d3a7fd20073bf3cff2.html
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int N = 2000;
int a[N],b[N],d[N];
string s;
int shift,ad,n,cnt,tt;
bool work(int l,int r,int x)
{
shift = 0;
memset(d, 0 ,sizeof(d) ) ;
for (int i = l;i>=0;--i)
{
shift = b[i] * x+shift;
d[i] = shift % 10;
shift /=10;
}
cnt = l+1;
//if (shift>0) d[0] = shift,++cnt;
tt = 0;
while (d[tt] == 0 && tt<=l) --cnt,++tt;
while (l<=r && a[l] == 0) ++l;
if (r-l+1<cnt) return 0;
if (r-l+1>cnt) return 1;
for (int i = l;i<=r;++i)
{
if (a[i]<d[tt]) return 0;
if (a[i]>d[tt]) return 1;
++tt;
}
return 1;
}
int main()
{
while (cin >> s)
{
memset(a,0,sizeof(a) );
memset(b,0,sizeof(b) );
if (s.size() % 2 == 1) ad = 4; else ad =3 ;
for (int i = 0;i< s.size(); i++)
a[i+ad] = s[i]-'0';
n = s.size()+ad-1;
for (int i = 2;i<=n/2;++i)
{
b[i-1] = b[i-1] * 2;
int shift = 0;
for (int j = i-1;j>=0;--j)
{
shift += b[j];
b[j] = shift % 10;
shift /= 10;
if (shift == 0) break;
} // shift b
for (int j = 9;j>=0;--j)
{
b[i] = j;
if (work(i,2*i,j) ) break;
} // try x
cout << b[i];
tt = 2*i; shift = 0;
for (int j = i;j>=0; --j)
{
shift = a[tt]+10+shift-d[j];
a[tt] = shift % 10;
shift /= 10;
--shift;
--tt;
}
}
printf("\n");
}
return 0;
}