高精度开根
【问题描述】
你所在的工作组正在编写一套高精度科学计算的软件,一些简单的部分如高精度加减法、乘除法早已写完了,现在就剩下你所负责的部分:实数的高精度开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); }