问题是找到数字的第n个根,如果根是一个整数i
需要打印它,否则我将打印-1。我曾经使用过这种方法,但我得到了。有没有比我实施的更快的方法?
这是我的代码:
public class Sqrt {
public static double nthroot(int n, double x)//calculates root
{
return Math.pow(x,1./n);
}
public static void main(String[] args) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int t,n,m;
double x;
String[] y;
t=Integer.parseInt(br.readLine());
while(t-->0)//test cases
{
y=br.readLine().split(" ");//to get number and the exp
n=Integer.parseInt(y[1]);//the exp
m=Integer.parseInt(y[0]);//the number
x=nthroot(m,n);
x=BigDecimal.valueOf(x)
.setScale(5, RoundingMode.HALF_UP)
.doubleValue();//to set precision upto 5 decimal places
if(x==(int)x)// **checks whether the root obtained is integer or not**
{
System.out.println((int)x);
}
else
{
System.out.println(-1);
}
}
}
}
答案 0 :(得分:1)
最快(针对许多查询进行了优化)将为所有非平凡根(exp = 2,3,4,5,...
)创建 SoE (Eratosthenes筛选)表。
x^(1/2)
的表格为(10^9)^(1/2) = 31622
整数。对于x^1/3
,它只是1000
个整数,并且数字随指数递减...您可以使用整数位宽度除法来获取表格大小而不是pow ...
例如x^(1/3)
的 SoE 就像这样在C ++中:
const bits=32; // binary bits count of 10^9
int e = 3; // rooth exponent
int n =1<<(1+bits/e); // table size
int *soe=new int [n+1];
int x;
for (x=0;x<=n;x++) soe[x]=x*x*x;
现在soe[]
保存{ 0,1,27,64,125,...}
,它们都是整数立方根。所以对于立方根上的任何查询,你只需要搜索soe
表,如果找到完全匹配,则返回soe中的索引,否则返回-1。
你可以为每个指数构建一个soe表(1除外),例如soe[exp-2][]
......
如果你想在没有 SoE 的情况下构建它,那么只使用整数二进制搜索:
[Edit1]这里简单的32位C ++(抱歉我不用JAVA编写代码)示例:
//---------------------------------------------------------------------------
//typedef uint32_t DWORD; // uncomment this if no DWORD type is present
//typedef uint16_t WORD; // uncomment this if no WORD type is present
const int _nroot_maxe=30; // max exponent
DWORD *soe[_nroot_maxe+3]={NULL}; // soe[][]
DWORD soen[_nroot_maxe+3]; // soe[e] size
DWORD soem[_nroot_maxe+3]; // soe[e] index MSB mask
//---------------------------------------------------------------------------
void mul(DWORD &h,DWORD &l,DWORD x,DWORD y) // (h,l) = x * y
{ // 64 = 32 * 32 bits
const int _h=1; // this is platform dependent MSW/LSW order !!!
const int _l=0;
union _u
{
DWORD u32;
WORD u16[2];
}u;
DWORD al,ah,bl,bh;
DWORD c0,c1,c2,c3;
// separate 2^16 base digits
u.u32=x; al=u.u16[_l]; ah=u.u16[_h];
u.u32=y; bl=u.u16[_l]; bh=u.u16[_h];
// multiplication (al+ah<<1)*(bl+bh<<1) = al*bl + al*bh<<1 + ah*bl<<1 + ah*bh<<2
c0=(al*bl);
c1=(al*bh)+(ah*bl);
c2=(ah*bh);
c3= 0;
// propagate 2^16 overflows (backward to avoid overflow)
c3+=c2>>16; c2&=0x0000FFFF;
c2+=c1>>16; c1&=0x0000FFFF;
c1+=c0>>16; c0&=0x0000FFFF;
// propagate 2^16 overflows (normaly to recover from secondary overflow)
c2+=c1>>16; c1&=0x0000FFFF;
c3+=c2>>16; c2&=0x0000FFFF;
// (c3,c2,c1,c0) -> (h,l)
u.u16[_l]=c0; u.u16[_h]=c1; l=u.u32;
u.u16[_l]=c2; u.u16[_h]=c3; h=u.u32;
}
//---------------------------------------------------------------------------
void nroot_init() // init SoE tables for nroot
{
DWORD i,e,n,m,h,l;
// compute table sizes
soen[0]=0; soem[0]=0;
soen[1]=0; soem[1]=0;
for (n=0,e=2;e<=_nroot_maxe;e++)
{
i=1<<((31+e-1)/e);
soen[e]=i;
n+=i;
}
// allocate memory and set pointers
soe[0]=new DWORD[n];
for (e=1;e<=_nroot_maxe;e++) soe[e]=soe[e-1]+soen[e-1];
// soe
for (e=2,i=0;i<soen[e];i++) soe[e][i]=i*i;
for (e=3;e<=_nroot_maxe;e++)
for (i=0;i<soen[e];i++)
{
mul(h,l,i,soe[e-1][i]); // 32bit * 32bit = 64bit
if (!h) soe[e][i]=l; // if no 32bit overflow store result
else soen[e]=i; // stop otherwise
}
// compute bin search index masks
for (m=0x80000000,e=2;e<=_nroot_maxe;e++)
{
while (m>=soen[e]) m>>=1; m<<=1;
soem[e]=m;
}
}
//---------------------------------------------------------------------------
void nroot_exit() // release SoE tables (free memory)
{
// release memory
if (soe[0]!=NULL) delete[] soe[0];
for (DWORD e=0;e<=_nroot_maxe;e++)
{
soe[e]=NULL;
soen[e]=0;
soem[e]=0;
}
}
//---------------------------------------------------------------------------
int nroot(DWORD x,DWORD e) // e-th root of x or -1 if not integer result
{
// special cases
if (e==0) return -1;
if (e==1) return x;
if (e>_nroot_maxe) return -1;
// init if needed
if (soe[0]==NULL) nroot_init();
// binary search
DWORD m,i;
for (i=0,m=soem[e];m;m>>=1)
{
i|=m;
if ((i>=soen[e])||(soe[e][i]>x)) i^=m;
}
if (soe[e][i]==x) return i;
return -1;
}
//---------------------------------------------------------------------------
对于那些没有DWORD
或WORD
取消注释typedef或更改为平台上无符号32位和16位整数的人...同时将_h,_l
常量设置为匹配您的平台。
即使这样也可以加快......只要意识到对于更高的指数,可能只有0,1,2,3 ... 0,1
个指数......
必须只调用一次init函数。在我的设置上,~0.187ms
花了几乎可以忽略不计。对所有1000000000
第5根进行测试需要~16sec