大整数开方

题目

大整数开方,求整数部分,\(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]);
}
posted @ 2020-12-12 11:54  leiyuanze  阅读(167)  评论(0编辑  收藏  举报