大整數開方
阿新 • • 發佈:2020-12-12
題目
大整數開方,求整數部分,\(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]); }