2018.4.29T3高精度开根

高精度开根

【问题描述】

你所在的工作组正在编写一套高精度科学计算的软件,一些简单的部分如高精度加减法、乘除法早已写完了,现在就剩下你所负责的部分:实数的高精度开m次根。

因为一个有理数开根之后可能得到一个无理数,所以这项工作是有较大难度的。你现在要做的只是这项工作的第一步:只对自然数进行开整数次根,求出它的一个非负根,并且不考虑结果的小数部分,只要求把结果截断取整即可。

【任务描述】

你的程序需要根据给定的输入,给出符合题意的输出:

l  输入包括需要开根的次数,以及被开根的整数;

l  你需要根据输入计算出它的非负根取整后的结果。

【输入格式】

输入文件calc.in共有两行,每行都有一个整数,并且输入中没有多余的空格:

l 第一行有一个正整数m (1 <= m <= 50),表示要开的根次;

l 第二行有一个整数n (0<=n <= 10^10000),表示被开根的数。

【样例输入】

3

1000000000

说明:对于输入示例,需要做的是把1,000,000,000开3次根。


【输出格式】

输出文件只有一行,包括一个数,即为开根取整后的结果。

【输出样例】

1000

【数据规模】

对于30%的数据,位数<=10

对于90%的数据,位数<=1000

对于100%的数据,位数<=10000

 ------------------------------------------------------------------

原题:bzoj1213

高精毁人生!

其实就是对答案进行二分,每次乘起来比较即可,本题数据弱,不卡常过不了bzoj,bzoj上要NTT。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10005,INF=100000000;
struct node{long long a[N];int siz;}l,r,mid,n;
inline void write(node x) {
	printf("%lld",x.a[x.siz]);
	for (int i=x.siz-1;i>=1;i--) {
		for (int j=INF/10;j>=10;j/=10)
				if (x.a[i]<j) putchar('0');
		printf("%lld",x.a[i]);
	}
	puts("");
}
inline void read(node &n) {
	char a[N];
	gets(a);n.siz=0;
	for (int i=strlen(a)-1;i>=0;) {
		n.siz++;
		for (int j=7;j>=0;j--)
			if (i-j>=0) n.a[n.siz]=n.a[n.siz]*10+a[i-j]-'0';
		i-=8;
	}
}
inline bool operator <(node x,node y) {
	if (x.siz!=y.siz) return x.siz<y.siz;
	for (int i=x.siz;i>=1;i--)  {
		if (x.a[i]!=y.a[i]) return x.a[i]<y.a[i];
	}
	return 0;
}
inline node operator +(node x,node y) {
	for (int i=1;i<=x.siz || i<=y.siz;i++) {
		x.a[i]+=y.a[i];
		x.a[i+1]+=x.a[i]/INF;
		x.a[i]%=INF;
	}
	x.siz=max(x.siz,y.siz);
	if (x.a[x.siz+1]) x.siz++;
	return x;
}
inline node operator *(node x,node y) {
	node b;
	memset(b.a,0,sizeof b.a);
	for (int i=1;i<=x.siz;i++) 
		for (int j=1;j<=y.siz;j++)
			b.a[i+j-1]+=x.a[i]*y.a[j];
	b.siz=x.siz+y.siz-1;
	for (int i=1;i<b.siz;i++) {
		b.a[i+1]+=b.a[i]/INF;
		b.a[i]%=INF;
	}
	while (b.a[b.siz]>=INF) {
		b.a[b.siz+1]+=b.a[b.siz]/INF;
		b.a[b.siz]%=INF;
		b.siz++;
	}
	return b;
}
inline node operator /(node x,int y) {
	for (int i=x.siz;i>=1;i--) {
		x.a[i-1]+=(x.a[i]%y)*INF;
		x.a[i]/=y;
	}
	while (!x.a[x.siz]) x.siz--;
	return x;
}
inline node operator +(node x,int y) {
	x.a[1]+=y;int k=1;
	while (x.a[k]>=INF) {
		x.a[k+1]+=x.a[k]/INF;
		x.a[k]%=INF;
		k++;
	}
	if (x.a[x.siz+1]) x.siz++;
	return x;
}
inline node operator -(node x,int y) {
	x.a[1]-=y;int k=1;
	while (x.a[k]<0) {
		x.a[k]+=INF;
		x.a[k+1]--;
		k++;
	}
	if (!x.a[x.siz]) x.siz--;
	return x;
}
int main () {
	freopen("calc.in","r",stdin);
	freopen("calc.out","w",stdout);
	int m;
	scanf("%d ",&m);
	read(n);
	l.siz=max(1,n.siz/m);l.a[l.siz]=1;
	r.siz=n.siz/m+2;r.a[r.siz]=1;
	while (l+1<r) {
		mid=(l+r)/2;
		node t=mid;int flag=1;
		for (int i=1;i<m;i++) {
			t=t*mid;
			if (n<t) break;
		}
		if (n<t) flag=0;
		if (!flag) r=mid-1;
		else l=mid;
	}
	node t=r;
	for (int i=1;i<m;i++) {
		t=t*r;
	}
	if (n<t) write(l);
	else write(r);
}

猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80169953