微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

求解大数模方程的有效方法

如何解决求解大数模方程的有效方法

我正在尝试求解以下方程 (x * 0x5DEECE66D + 11) mod 2^47 = 0x310CDAF20000 其中 WolframAlpha is able to solve in a few seconds

我想出了以下简单的 C++ 代码,用 & 替换 modulo,遗憾的是效率不够高,而且需要很长时间才能完成:

auto target = 0x310CDAF20000LL;
auto devider = 0x5DEECE66DLL;
auto mask = 1LL << 48 - 1;
auto i = 1LL;

while (1) {
    if ((i * devider + 11) & mask == target) {
        printf("%llx",i);
        break;
    }
    i++;
}

有什么建议吗?

解决方法

从这里开始

25214903917 * x = 53931282661365 (mod 2^47)

根据欧拉定理,你知道

25214903917 ^ phi(2^47) = 1 (mod 2^47)

在这种情况下,欧拉的整数很容易计算为 (2^47)/2 = 2^46。所以

25214903917 * 25214903917 ^ (phi(2^47) -1) = 1 (mod 2^47)
25214903917 * 25214903917 ^ (2^46 -1) = 1 (mod 2^47)
25214903917 * (53931282661365 * 25214903917 ^ (2^46 -1)) = 53931282661365 (mod 2^47)
x = 53931282661365 * 25214903917 ^ (2^46 -1) (mod 2^47)

您可以通过平方来使用求幂来计算求幂。代码非常简单(在 C# 中)

long desiredResult = 53931282661365;
long q = 25214903917;

long invq = 1;
long tmp = q;
for(int i = 0; i < 46; ++i)
{
    // tmp is q^(2^i)
    invq = (invq * tmp) & 0x7FFFFFFFFFFF;
    tmp = (tmp * tmp) & 0x7FFFFFFFFFFF; 
}
// invq is 105417217348453

long x = (invq * desiredResult) & 0x7FFFFFFFFFFF;
// x is 91896827357865

long test = (q * x) & 0x7FFFFFFFFFFF;
// test is 53931282661365

整个解为n * 2^47 + x,对应WolframAlpha

,

如果 (x * 0x5DEECE66D + 11) mod 2^47 = 0x310CDAF20000 为真,则 (x * 0x5DEECE66D) mod 2^47 = 310CDAF1FFF5 为真(对于非负 x 可能,取决于 mod 的定义方式)。

将所有内容向左移动 17 位不会改变任何内容。换句话说,如果 (x * 0x5DEECE66D) mod 2^47 = 310CDAF1FFF5(x * 2EF767336800000) mod 2^64 = 866D78FFFA800000

对于计算机,使用 64 位(无符号)整数和标准的“截断以适应”这意味着可以删除 mod

下一步;如果 (x * 2EF767336800000) mod 2^64 = y 那么 ( (x+1) * 2EF767336800000) mod 2^64 = (y + 2EF767336800000) mod 2^64

换句话说,从 x = 0(很明显 (x * 2EF767336800000) mod 2^64 = 0)开始,您可以使用“add then AND”来确定 x = 1 的结果,然后对 { 执行相同操作{1}},然后...

这导致:

x = 2

更进一步的是意识到如果 auto target = 0x310CDAF20000LL; auto devider = 0x5DEECE66DLL; auto i = 1LL; auto t = (target - 11) << 17; auto d = devider << 17; uint64_t temp = 0; do { temp += d; i++; } while(temp != t); 那么 (x * 2EF767336800000) mod 2^64 = y。这意味着如果您有 8 个起始值(( (x+8) * 2EF767336800000) mod 2^64 = (y + 2EF767336800000 * 8) mod 2^64x = 0),您可以使用 SIMD 并行处理 x = 7 的 8 个值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。