我正在进行加密练习,我正在尝试计算(2 n -1)mod p,其中p是素数
这样做的最佳方法是什么?我正在使用C这样2 n -1变得太大而无法在n很大时保持
我遇到了等式(a * b)modp =(a(bmodp))modp,但我不确定这适用于这种情况,因为2 n -1可能是素数(或者我不确定如何将其分解)
非常感谢。
答案 0 :(得分:6)
一些提示可以帮助您找到更好的方法:
答案 1 :(得分:1)
您在评论中提到n
和p
是9位或10位数字。如果将它们限制为32位(unsigned long
)值,则可以使用简单(二进制)模幂运算找到2^n mod p
:
unsigned long long u = 1, w = 2;
while (n != 0)
{
if ((n & 0x1) != 0)
u = (u * w) % p; /* (mul-rdx) */
if ((n >>= 1) != 0)
w = (w * w) % p; /* (sqr-rdx) */
}
r = (unsigned long) u;
并且,因为(2^n - 1) mod p = r - 1 mod p
:
r = (r == 0) ? (p - 1) : (r - 1);
如果2^n mod p = 0
- 如果p > 2
为素数,则实际上不会发生 - 但我们不妨考虑一般情况 - 然后(2^n - 1) mod p = -1 mod p
。
由于'公共残留'或'余数'(mod p)
位于[0, p - 1]
,我们会添加p
的倍数,以便它在此范围内。
否则,2^n mod p
的结果位于[1, p - 1]
,减去1
已经在此范围内。它可能更好地表达为:
if (r == 0)
r = p - 1; /* -1 mod p */
else
r = r - 1;
答案 2 :(得分:0)
要获取模数,你必须要有2 ^ n-1,否则你将以不同的算法方向移动,有趣但分开的方向,所以我建议你使用大的int概念,因为它很容易... make一个结构,并在小值中实现一个很大的价值,例如
struct bigint{
int lowerbits;
int upperbits;
}
语句的分解也有解如2 ^ n =(2 ^ n-4 * 2 ^ 4)-1%p分解并分别处理它们,那将是非常算法的
答案 3 :(得分:0)
要计算2 ^ n - 1 mod p,您可以在首先从n中删除(p - 1)的任意倍数(因为a ^ {p-1} = 1 mod p)后通过平方来使用取幂。在伪代码中:
n = n % (p - 1)
result = 1
pow = 2
while n {
if n % 2 {
result = (result * pow) % p
}
pow = (pow * pow) % p
n /= 2
}
result = (result + p - 1) % p
答案 4 :(得分:0)
我在解决HackerRank上的一个数学问题时遇到了我在这里发布的答案,并且它已经适用于那里给出的所有给定测试用例。
如果将n
和p
限制为64位(无符号长整数)值,则以下是数学方法:
2^n - 1
可以写成1*[ (2^n - 1)/(2 - 1) ]
如果仔细观察,这是GP 1 + 2 + 4 + .. + 2^(n-1)
瞧,我们知道(a+b)%m = ( (a%m) + (b%m) )%m
如果您对添加的上述关系是否属实感到困惑,可以谷歌搜索它,或者您可以查看以下链接:http://www.inf.ed.ac.uk/teaching/courses/dmmr/slides/13-14/Ch4.pdf
所以,现在我们可以将上述关系应用于我们的GP,你会得到你的答案!
那是,
(2^n - 1)%p
相当于( 1 + 2 + 4 + .. + 2^(n-1) )%p
,现在应用给定的关系。
答案 5 :(得分:-1)
首先,关注2 n mod p,因为你总是可以减去一个。
考虑两个人的权力。这是通过重复乘以2产生的一系列数字。
考虑模运算。如果数字是用基数p写的,那么你只需抓住最后一位数。可以扔掉更高的数字。
所以在序列中的某个点上,你得到一个两位数的数字(在p的位置为1),你的任务实际上只是为了摆脱第一个数字(减去p)
在概念上停止这里,蛮力方法将是这样的:
uint64_t exp2modp( uint64_t n, uint64_t p ) {
uint64_t ret = 1;
uint64_t limit = p / 2;
n %= p; // Apply Fermat's Little Theorem.
while ( n -- ) {
if ( ret >= limit ) {
ret *= 2;
ret -= p;
} else {
ret *= 2;
}
}
return ret;
}
不幸的是,对于大的n和p,这仍然需要永远,我无法想到任何更好的数论。
如果你有一个可以计算(p-1)^ 2而没有溢出的乘法工具,那么你可以使用一个类似的算法,在每个平方操作后使用模数重复平方,然后取一系列正方形的乘积残差,每次乘法后再用一个模数。
答案 6 :(得分:-2)
步骤1. x =移位1 n次然后减去1
步骤2.result =逻辑和x和p的操作