计算的最佳方法((2 ^ n)-1)mod p

时间:2013-11-04 07:39:09

标签: c primes modulo

我正在进行加密练习,我正在尝试计算(2 n -1)mod p,其中p是素数

这样做的最佳方法是什么?我正在使用C这样2 n -1变得太大而无法在n很大时保持

我遇到了等式(a * b)modp =(a(bmodp))modp,但我不确定这适用于这种情况,因为2 n -1可能是素数(或者我不确定如何将其分解)

非常感谢。

7 个答案:

答案 0 :(得分:6)

一些提示可以帮助您找到更好的方法:

  1. 不要使用(a * b)modp =(a(bmodp))modp来计算2 n -1 mod p,用它来计算2 n mod p然后减去。
  2. Fermat's little theorem在这里很有用。这样,您实际需要处理的指数不会超过p。

答案 1 :(得分:1)

您在评论中提到np是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上的一个数学问题时遇到了我在这里发布的答案,并且它已经适用于那里给出的所有给定测试用例。

如果将np限制为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的操作