performance - 求解具有大量数字的模方程的有效方法
问题描述
我正在尝试解决WolframAlpha 能够在几秒钟内(x * 0x5DEECE66D + 11) mod 2^47 = 0x310CDAF20000
解决的以下方程
我想出了以下琐碎的C++
代码,将模替换为&
,遗憾的是效率不够高,需要很长时间才能完成:
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)
在这种情况下,欧拉的 totient 很容易计算为 (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
推荐阅读
- python - 使用 openpyxl 创建两个 y 轴图表
- swift - 快速操场上的斐波那契
- php - 如何使用 AJAX 发布请求更改 HTML DOC 的背景颜色:
- opengl - 简单来说,textureGrad() 是什么?
- android - 满足条件时使肯定按钮无效
- python - 创建一个多元偏斜正态分布python
- redis - DigitalOcean pod 具有未绑定的即时 PersistentVolumeClaims
- wpf - 如何防止将我的应用程序的第一个菜单项集中在启动时?
- google-cloud-platform - 谷歌云平台:cloudshell - 有没有办法“保留” gcloud init 配置?
- r - lapply 或 sapply 用于 List 中的 data.frames