[英]Best way to store large base B numbers?
存储大型基本B编号的最佳方法是什么,以便能够有效地完成右移和检查最低有效位等操作?
实际上,我遇到了一个面试问题
Given two numbers N and K such that 0<=N<=1000 and 0<=K<=1000^1000. I need
to check that whether N^N = K or not. For example:
if N=2 and K=4 , 2^2 = 4 so return true;
if N=3 and K=26 , 3^3 != 26 so return false
我在想的是,如果我考虑base N number system
,那么N^N
将等于1 followed by N zero
。 例如 - 对于N = 2,2 ^ 2 = 100(在基数2中),对于N = 3,3 ^ 3 = 1000(在基数3中)。 然后,我可以轻松编写一个函数来判断K = N^N
是否。
int check(unsigned long int N, unsigned long int K)
{
unsigned long int i;
for (i=0; i<N; i++)
{
if (K%N != 0) //checking whether LSB is 0 or not in base N number system
return 0;
K = K/N; //right shift K by one.
}
return (K==1);
}
现在这个功能有两个主要问题:
1) An unsigned long int is not sufficient to store large numbers of range 0
to 1000^1000.
2) The modulus and the division operations makes it every less efficient.
为了使其高效,我正在寻找一些方法来表示大的基数N数,以便我可以执行右移并有效地检查最低有效位操作。 以前有人遇到过这样的事吗? 或者有谁知道有效解决这个问题的任何其他方法?
要检查相等性,您实际上不必进行高精度算术 - 您可以使用http://en.wikipedia.org/wiki/Chinese_remainder_theorem 。 找到足够的质数以确保它们的乘积大于N ^ N,然后依次检查N ^ N对K的每个质数的模数。
在实践中,我可能会使用Java BigInteger包进行简单的计算。
根据面试官的不同,可以接受一些答案。 如果其中任何一项都不被接受,那么希望面试官能够迅速推动您提出其他建议。
gmp
,或者使用mpz_t
而不是unsigned long
来执行除法和模数,或者只计算N^N
并将其与K
进行比较。 这是最简单的方法。 K
在N^N
附近时很多工作。 例如,测试log(K) / N
是否近似等于log(N)
,在任何基数中采用的日志对于输入最方便。 或测试多少次K
和N
是整除的数字方便像2
或10
:如果K
是不能分开的正是N
次很多次N
,那么它显然是错误的。 或者测试它们是否等于一些小数,例如ULONG_MAX
或1000000
。 不幸的是,这种事情只能加速某些不平等的情况,它会减慢其他一切,包括它们的情况。 所以它可能适得其反,取决于你期望的输入。 mcdowella的回答可能是也可能不是最好的,我不知道。 特别有希望的是,您只需要生成一次素数(当您编写程序时),并且在100 N <= 1000
从1009开始的1000个素数就足够了。 较大的素数意味着需要的更少,因此工作量更少,特别是如果它们不超过ULONG_MAX
平方根。 通过平方或等效使用取幂来得到N^N
模数每个素数,并且对于K
,无论输入是什么基础,每次都做几个数字。
要真正闪存,对于每个预先选择的素数p
您可以编写(或让编译器为您编写)模运算操作,该操作比适用于任何除数的一般整数模运算更快。 也就是说,一个体面的编译器i % 1009
可能会快于i % j
其中的价值j
是在编译时未知,但原来在运行时是1009。但要注意,在速度上的差异可能收不回(比如)通过函数指针调用它的成本。 因此,利用它可能需要一些丑陋的重复代码。
为什么要将数字转换为基数N?
你可以继续除以N.如果你在N之后得到1这样的除数那么它就是N ^ N. 否则它不是。
您必须将K存储为字符串并执行divison操作。
divide(k,n):
c = ''
a = ''
for i in k:
c = c+i
a = a+ str(int(c)/ int(n))
c = str(int(c) % int(n))
return a
这是在python中,你可以在C中实现类似的东西
给定两个数字N和K,使得0 <= N <= 1000且0 <= K <= 1000 ^ 1000。 我需要检查是否N ^ N = K.
很大程度上取决于提供给代码时这些数字的存储方式。 假设它们是文本格式,我只是保持这种方式,并创建一个包含N ^ N值的1001个字符串数组。 您可以使用任意精度算术命令行程序(如bc
来一次性创建这些字符串,并在循环中调用它。
由于1000 ^ 1000中只有1000个“好”值(并且它们将彼此相距很远),因此可以先使用一些对数近似来猜测N. 在那之后,您最多只需要一次精确检查(例如,使用一些bignum库)。
这个对数不必是精确的,即使strlen()可以足够近似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.