【NOIP2011初赛】大整数开方

题目

Description

输入一个正整数n(1<=n<=10^100),输出n的平方根的整数部分。

Input

正整数n

Output

n的平方根的整数部分

Sample Input

10

Sample Output

3

Data Constraint

n ≤ 1 0 100 n\le10^{100} n10100

题解

题目大意

求一个大数的平方根的整数部分

题目分析

如果说 n n n小一点我们可以考虑二分,那么 n n n大了则可以高精度

这题是一个高精度综合板子题,有高精乘、高精除二,高精加一,高精减一,高精加,高精比较

Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct highcalc
{
	int len,num[10005];
};
highcalc l,r,mid,n,ans,res;
char sa[105];
bool small(highcalc x,highcalc y)
{
	if (x.len>y.len) return false;
	if (x.len<y.len) return true;
	for (int i=x.len;i;--i)
	{
		if (x.num[i]>y.num[i]) return false;
		if (x.num[i]<y.num[i]) return true;
	}
	return true;
}
void Plus(highcalc a,highcalc b,highcalc &c)
{
	for (int i=1;i<=max(a.len,b.len);++i)
	{
		c.num[i]+=a.num[i]+b.num[i];
		c.num[i+1]+=c.num[i]/10;
		c.num[i]%=10;
	}
	c.len=max(a.len,b.len);
	while (c.num[c.len+1])
	{
		c.len++;
		c.num[c.len+1]+=c.num[c.len]/10;
		c.num[c.len]%=10;
	}
}
void div2(highcalc &a)
{
	if (a.num[1]%2==1) a.num[1]--;
	for (int i=a.len;i;--i)
	{
		a.num[i-1]+=(a.num[i]%2)*10;
		a.num[i]/=2;
	}
	int st=a.len;
	while (!a.num[st]) --st;
	a.len=st;
}
void mul(highcalc a,highcalc b,highcalc &c)
{
	for (int j=1;j<=b.len;++j)
		for (int i=1;i<=a.len;++i)
		{
			c.num[i+j-1]+=a.num[i]*b.num[j];
			c.num[i+j]+=c.num[i+j-1]/10;
			c.num[i+j-1]%=10; 
		}
	c.len=a.len+b.len-1;
	while (c.num[c.len+1])
	{
		c.len++;
		c.num[c.len+1]=c.num[c.len]/10;
		c.num[c.len]%=10;
	}
}
void add1(highcalc &a)
{
	for (int i=1;i<=a.len;++i)
	{
		if (i==1) a.num[i]++;
		a.num[i+1]+=a.num[i]/10;
		a.num[i]%=10;
	}
	if (a.num[a.len+1]) a.len++;
}
void dec1(highcalc &a)
{
	for (int i=1;i<=a.len;++i)
	{
		if (i==1) a.num[i]--;
		if (a.num[i]<0) a.num[i]+=10,a.num[i+1]--;
	}
	while (!a.num[a.len]&&a.len>0) a.len--; 
}
int main()
{
	cin>>sa;
	l.len=l.num[1]=1;
	n.len=r.len=strlen(sa);
	for (int i=0;i<r.len;++i)
		n.num[i+1]=r.num[i+1]=sa[r.len-i-1]-'0';
	while (small(l,r))
	{
		for (int i=1;i<=mid.len;++i) 
			mid.num[i]=0;
		mid.len=0;
		Plus(l,r,mid);
		div2(mid);
		for (int i=1;i<=res.len;++i) 
			res.num[i]=0;
		res.len=0;
		mul(mid,mid,res);
		if (small(res,n))
		{
			l.len=ans.len=mid.len;
			for (int i=1;i<=ans.len;++i)
				l.num[i]=ans.num[i]=mid.num[i];
			add1(l);
		}
		else 
		{
			r.len=mid.len;
			for (int i=1;i<=mid.len;++i)
				r.num[i]=mid.num[i];
			dec1(r);
		}
	}
	for (int i=ans.len;i;--i)
		printf("%d",ans.num[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值