找到满足模数的最小值

时间:2014-02-20 07:11:27

标签: c math optimization hash modulus

我遇到的问题是x =(16807 x k)%65536

即16807k≡x(mod 65536)

我需要计算知道x的k。 到目前为止,我的最大努力是一种蛮力。有没有数学方法来计算k? 如果不是我的当前代码的任何优化将不胜感激。

t = x;
while ( t += 15115 ) // 16807k = 65536n + x - this is the n
{
    if (t%16807 == 0)
    return t/16807;
}
return x;

编辑:将+ =更改为15115

4 个答案:

答案 0 :(得分:6)

奇数具有乘法逆模,其幂为2。

16807 mod 2 16 的倒数是22039。

这意味着(16807 * 22039) % 65536 == 1,因此,

(16807 * 22039 * x) % 65536 == x

k = (22039 * x) % 65536

因此您无需尝试任何操作,只需直接计算k即可。

答案 1 :(得分:1)

使用扩展欧几里德算法为16807和65536的GCD解决此类问题

剩余序列以

开始
R0=65536
R1=16807

的逆运算
V0=0  (V0*16807 == R0 mod 65536)
V1=1  (V1*16807 == R1 mod 65536)

然后使用整数长除法

Q1=R0/R1=3,
R2=R0-Q1*R1=15115
V2=V0-Q*V1=-3 (V2*16807 == R2 mod 65536)

Q2=R1/R2=1,  
R3=R1-Q2*R2=1692
V3=V1-Q2*V2=4

Q3=8,  R4=1579,  V4=-35
Q4=1,  R5=113,   V5=39
Q5=13, R6=110,   V6=-542
Q6=1,  R7=3,     V7=581
Q7=36, R8=2,     V8=-21458
Q8=1,  R9=1,     V9=22039

使得22039被发现为15115模数65536的模数逆。

答案 2 :(得分:0)

如果您必须针对不同的k反复查找x,则可以在开始解码之前构建解决方案表:

uint16_t g = 16807u;
uint16_t *mods = malloc(0x10000 * sizeof(*mods));
int i;

for (i = 0; i < 0x10000; i++) {
    uint16_t x = g * i;    // x is effectively x mod 2**16

    mods[x] = i;
};

在16位范围内对yor方程的解是:

uint16_t k = mods[x];

假设x是16位无符号整数。完成后不要忘记free(mods)

答案 3 :(得分:0)

如果k是解决方案,那么k+65536也是一种解决方案。

找到第一个k(k> = 0)的简单蛮力方法是:

for (k=0; k < 65536; k++) {
    if ( (k*16807) % 65536 == x ) {
        // Found it!
        break;
    }
}
if (k=65536) {
    // No solution found
}
return k;