查找 a,b,n 以便 (a^b)%n=x

Find a,b,n so that (a^b)%n=x

本文关键字:以便 查找      更新时间:2023-10-16

假设我为 x 选择一个介于02147483647之间的值。(Int32.MaxValue( 我正在尝试弄清楚如何找到a,b,n的值,以便(a^b)%n=x我已经知道我可以使用 ModPow 来验证值,但我不知道如何找到合适的 a、b 和 n。

#include <iostream>
/// Calculate (a^b)%n
/// param a The base
/// param b The exponent
/// param n The modulo
/// return (a^b)%n
int ModPow(int a, int b, int n) {
long long x = 1, y = a;
while (b > 0) {
if (b % 2 == 1) {
x = (x * y) % n; // multiplying with base
}
y = (y * y) % n; // squaring the base
b /= 2;
}
return x % n;
}
int main() {
int x = 1337;
// How to find a,b,n so that (a^b)%n=x
int a = ?;
int b = ?;
int n = ?;
if(x == ModPow(a,b,n))
printf("ok");
return 0;
}
int n = 2147483647
int a = ModPow(x, 9241, n);
int b = 464773;

n= 231− 1 是质数。因此,由于费马小定理,x n mod n = x 和 x n − 1 modn = 1(除非 x = 0(,所以 x 2 n− 1modn=x2n− 1 = 9241 × 464773。所以 (x9241mod n(464773modn=x请注意,您需要x<<em>n 才能正常工作;x= 如果n也是 31 位(即有符号(整数,则 2147483647 不起作用。

我花了一段时间才来到这里;在我得出这个简单的解决方案之前,很长一段时间以来,我一直有这个答案弄乱了卡迈克尔数字和卡迈克尔函数。有关详细信息,请参阅编辑历史记录。

模运算符:

产生以下表达式给出的余数,其中 e1 是第一个操作数,e2是第二个操作数:e1 – (e1/e2( * e2

因此,无论x的最大值是多少,n都必须更大。由于您将n作为int进行验证,并且您指定了范围:0numeric_limits<int>::max(),这必须是独占范围,并且要使n成为int它唯一可能的值是:numeric_limits<int>::max()

n强制的情况下,我们的方程实际上变成了:ab=x
我们需要在这里检查x不是1,如果它是b= 0并且a可以是我们合法范围内的任何东西,因此我们可以任意选择a= 2。但除此之外:

我们的要求是:

  • 1<a><x>aint
  • 1<b><x>bint

给定x,我们可以搜索适合如下的ab的组合:

auto a = 0.0;
auto b = 1;
if(x == 1) {
a = 2.0;
b = 0;
} else {
while((a = pow(x, 1.0 / ++b)) > 2.0) {
double dummy;
if(modf(a, &dummy) == 0.0) {
break;
}
}
}

此时,如果a>= 2.0,则有一个有效的问题解决方案。现在您可能已经知道,pow是一个非常昂贵的函数,因此对于较大的x值,这可能需要很长时间才能执行,我个人建议为每个存在这种对的数字找到一个ab并将它们存储在map中并对其进行查找。
无论如何,这是工作代码的演示:

现场示例