我遇到的问题是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
答案 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;