Description
This problem involves the efficient computation of integer roots of numbers.
Given an integer n>=1 and an integer p>= 1 you have to write a program that determines the n th positive root of p. In this problem, given such integers n and p, p will always be of the form k to the nth. power, for an integer k (this integer is what your program must find).
Input
Output
Sample Input
2 16
3 27
7 4357186184021382204544
Sample Output
4
3
1234
poj最近在维护……然后一段时间内就都不能提交了。。
先挂着。。
方法比较简单,考虑到结果的大小是有二分性的,
所以可以二分一个值,然后判断是否合法即可。
写个结构体,然后就简单了很多……
说说另外的做法。。
本来看到求x^m=a的x,想到牛顿迭代就来看看……结果还是高精度。。
还是提一提吧。。
我们要求解x^m=a的解x,设f(x)=x^m-a,那么题目转化为求f(x)的零点。
写出f(x)的近似泰勒展开,,(泰勒级数不会自行百度= =)
f(x)=f(x0)+(x-x0)*f'(x0)=0
其中f'(x0)是f(x0)的一阶导数,x0是一个近似解,
那么解出x就可以得到一个方程的近似解。。
注意是近似的,因为原本的展开是无穷的,这只是一个近似展开。。
但是显然精度很大时候会不够……
这个时候就可以利用一个迭代的思想:
上面的式子=0两边同时除以f'(x0),得到:
x=x0-f(x0)/f'(x0)
用x作为新的x0继续迭代,直到x在某一个精度范围内,
那么就得到了这个方程的某个近似解。
对于这题,f(x)=x^m-a,
f'(x)=m*x^(m-1)
根据这个迭代即可。
但是事实上如果要高精度的话,这个迭代会牵扯到高精度除法……
解决方法挺简单,解除f(x)=(1/x)^m-a的零点(模拟小数高精度),
然后就只用做一遍高精度除法了。
总的来说还是二分简便……但是乘法一慢就gg了= =
当然FFT什么的当然好哇。。
等到poj恢复了再交一发,现在精神AC一下……=v=
#include<bits/stdc++.h> using namespace std; const int maxn=505; struct BigNum{ int len,a[maxn]; BigNum(){len=0;memset(a,0,sizeof(a));} void read(){ char t[maxn]; scanf("%s",t+1); len=strlen(t+1); for (int i=1;i<=len;i++) a[i]=t[len-i+1]-'0'; } void print(){ for (int i=len;i;i--) printf("%d",a[i]); putchar('\n'); } BigNum operator =(int x){ char t[maxn]; sprintf(t+1,"%d",x); len=strlen(t+1); for (int i=1;i<=len;i++) a[i]=t[len-i+1]-'0'; return (*this); } BigNum operator =(BigNum x){ len=x.len; for (int i=1;i<=len;i++) a[i]=x.a[i]; return (*this); } bool operator <(BigNum x){ if (len<x.len) return 1; if (len>x.len) return 0; for (int i=len;i;i--){ if (a[i]<x.a[i]) return 1; if (a[i]>x.a[i]) return 0; } return 0; } bool operator >(BigNum x){return x<(*this);} bool operator >=(BigNum x){return !((*this)<x);} bool operator <=(BigNum x){return !((*this)>x);} bool operator ==(BigNum x){return (*this)<=x && (*this)>=x;} BigNum operator +(BigNum x){ BigNum y; y.len=max(len,x.len); for (int i=1;i<=y.len;i++){ y.a[i]+=x.a[i]+a[i]; y.a[i+1]=y.a[i]/10; y.a[i]%=10; } if (y.a[y.len+1]) y.len++; return y; } BigNum operator -(BigNum x){ BigNum mi,ma; if ((*this)>x) ma=(*this),mi=x; else ma=x,mi=(*this); for (int i=1;i<=ma.len;i++){ if (ma.a[i]-mi.a[i]>=0) ma.a[i]=ma.a[i]-mi.a[i]; else ma.a[i]=mi.a[i]-ma.a[i],ma.a[i+1]--; } return ma; } BigNum operator +(int x){BigNum y;y=x;return (*this)+y;} BigNum operator -(int x){BigNum y;y=x;return (*this)-y;} BigNum operator *(BigNum x){ BigNum y; y.len=x.len+len-1; for (int i=1;i<=len;i++) for (int j=1;j<=x.len;j++){ y.a[i+j-1]+=x.a[j]*a[i]; y.a[i+j]+=y.a[i+j-1]/10; y.a[i+j-1]%=10; } if (y.a[y.len+1]) y.len++; return y; } BigNum operator /(int x){ BigNum y;int t=0; y.len=len; while (t<x) t=t*10+a[y.len--]; y.a[++y.len]=t/x; for (int j=y.len-1;j;j--){ t=t%x*10+a[j]; y.a[j]=t/x; } return y; } BigNum operator ^(int y){ BigNum z,e; z=1;e=(*this); while (y){ if (y&1) z=z*e; e=e*e;y>>=1; } return z; } }; int main(){ BigNum a,l,r,mid,tmp; int b; while (~scanf("%d",&b)){ a.read(); l=1;r=a/(b-1); while (l<=r){ mid=(l+r)/2; tmp=mid^b; if (tmp==a){mid.print();break;} if (tmp>a) r=mid-1; else l=mid+1; } } return 0; }