存储大型基本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,以便我可以执行右移并有效地检查最低有效位操作。以前有人遇到过这样的事吗?或者任何人都知道有效解决这个问题的其他方法吗?
答案 0 :(得分:2)
要检查相等性,您实际上不必进行高精度算术 - 您可以使用http://en.wikipedia.org/wiki/Chinese_remainder_theorem。找到足够的质数以确保它们的乘积大于N ^ N,然后依次检查N ^ N对K的每个素数的模数。
实际上,我可能会使用Java BigInteger包来进行简单的计算。
答案 1 :(得分:2)
根据面试官的不同,可能会接受一些答案。如果其中任何一项都不被接受,那么希望面试官能够迅速推动您提出其他建议。
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
之类的小数。不幸的是,这种事情只能加速某些不平等的情况,它会减慢其他一切,包括它们的情况。所以它可能适得其反,取决于你期望的输入。N <= 1000
来说已经绰绰有余了。较大的素数意味着需要的更少,因此工作量更少,特别是如果它们不大于ULONG_MAX
的平方根。通过平方或等效使用取幂来获得每个素数的N^N
模数,并且K
在输入的任何基础上一次做几个数字。
要真正闪存,对于每个预先选择的素数p
,您可以编写(或让编译器为您编写)模数p操作,该操作比适用于任何素数的一般整数模运算快除数。也就是说,一个像样的编译器i % 1009
可能比i % j
更快,其中j
的值在编译时是未知的,但在运行时结果是1009.但要注意,速度的差异可能无法证明(比如)通过函数指针调用它的成本。因此,利用它可能需要一些丑陋的重复代码。
答案 2 :(得分:0)
为什么要将数字转换为基数N?
你可以继续除以N.如果你在N之后得到1这样的除数那么它就是N ^ N.否则它不是。
您必须将K存储为字符串并执行分割操作。
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
中实现类似的东西答案 3 :(得分:0)
给定两个数N和K使得0 <= N <= 1000且0 <= K <= 1000 ^ 1000。我需要检查是否N ^ N = K.
很大程度上取决于提供给代码时这些数字的存储方式。假设它们是文本格式,我只是保持这种方式,并创建一个包含N ^ N值的1001个字符串数组。您可以使用像bc
这样的任意精度算术命令行程序来一次性创建这些字符串,并在循环中调用它。
答案 4 :(得分:0)
由于1000 ^ 1000中只有1000个“好”值(并且它们将彼此相距很远),您可以先使用一些对数近似来猜测 N 。之后,您最多只需要一次精确检查(例如,使用一些bignum库)。
这个对数不一定非精确,即使 strlen()也足够近似。