大整数开方
题目
大整数开方,求整数部分,\(1 \le n \le 10^{400}\)
分析
二分即可
然后是高精基操
\(Code\)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[10005];
struct node{
int m[10005];
void clear(){memset(m, 0, sizeof m);}
}A, L, R, M, ans, I;
node Plus(node a, node b)
{
node c; c.clear();
c.m[0] = max(a.m[0], b.m[0]);
int g = 0;
for(register int i = 1; i <= c.m[0]; i++)
{
c.m[i] = a.m[i] + b.m[i] + g;
g = c.m[i] / 10, c.m[i] %= 10;
}
if (g) c.m[++c.m[0]] = g;
return c;
}
node Sub(node a)
{
--a.m[1];
int i = 1;
while (i <= a.m[0] && a.m[i] < 0) a.m[i] += 10 , a.m[++i] -= 1;
if (a.m[a.m[0]] == 0) --a.m[0];
return a;
}
node Mul(node a, node b)
{
node c; c.clear();
for(register int i = 1; i <= a.m[0]; i++)
{
int g = 0;
for(register int j = 1; j <= b.m[0]; j++)
{
c.m[i + j - 1] += a.m[i] * b.m[j] + g;
g = c.m[i + j - 1] / 10;
c.m[i + j - 1] %= 10;
}
c.m[i + b.m[0]] += g;
}
c.m[0] = a.m[0] + b.m[0];
while (c.m[c.m[0]] == 0 && c.m[0] > 1) c.m[0]--;
return c;
}
node Div(node a)
{
node c; c.clear();
int g = 0;
if (a.m[a.m[0]] > 1) c.m[0] = a.m[0];
else c.m[0] = a.m[0] - 1, g = a.m[a.m[0]] * 10;
for(register int i = c.m[0]; i; i--)
{
c.m[i] = (g + a.m[i]) / 2;
g = (g + a.m[i]) & 1, g *= 10;
}
return c;
}
int check(node a, node b)
{
if (a.m[0] < b.m[0]) return 1;
if (a.m[0] > b.m[0]) return 0;
for(register int i = a.m[0]; i; i--)
if (a.m[i] < b.m[i]) return 1;
else if (a.m[i] > b.m[i]) return 0;
return 1;
}
int main()
{
scanf("%s", s + 1);
A.m[0] = strlen(s + 1);
for(register int i = 1; i <= A.m[0]; i++) A.m[i] = s[A.m[0] - i + 1] - '0';
I.m[I.m[0] = 1] = 1, L = I, R = A;
while (check(L, R))
{
M = Div(Plus(L, R));
if (check(Mul(M, M), A)) ans = M, L = Plus(M, I);
else R = Sub(M);
}
for(register int i = ans.m[0]; i; i--) printf("%d", ans.m[i]);
}