【问题标题】:Best way to compute ((2^n )-1)mod p计算 ((2^n )-1)mod p 的最佳方法
【发布时间】:2013-11-14 19:40:03
【问题描述】:

我正在做一个密码练习,我正在尝试计算 (2n-1)mod p 其中 p 是一个素数

最好的方法是什么?我正在使用 C,所以当 n 很大时 2n-1 变得太大而无法容纳

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

非常感谢您的帮助。

【问题讨论】:

  • n和p的数值范围非常相关。
  • P 是 10 位素数(比如 1000000007),n 最多为 9 位。
  • 是 999999999 之前的任何 10 位素数,还是有特定的上限? 2^32 ≈ 4*10^9 是 10 位数字,所以问题是您是否可以对任何小于 p 的数字进行平方而不溢出本机 64 位整数类型。
  • 我可以选择我的素数,比如说,我选择它为 1000000007(前 10 位素数)

标签: c primes modulo


【解决方案1】:

一些提示可以帮助您想出更好的方法:

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

【讨论】:

  • 我更喜欢你在我的帖子,很好的回答
  • 但是我怎样才能“事后减去”呢?由于 mod 可能会在其中一个步骤中发生变化。例如。 (100mod100)=0 而 (100-1)mod100=(99mod100)=99。之后的减法如何工作?
  • 好吧,除非 p = 2,否则 2^n mod p 不会为 0。
  • (但一般情况下,你可以测试一下)
  • @navinpai: -1 mod 100 = 99。
【解决方案2】:

您在 cmets 中提到 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;

【讨论】:

  • 谢谢。这非常有效。但是你能解释一下最后一行吗?我不确定那在做什么
  • @navinpai - 这是ternary / conditional operator - 我会更新答案。
【解决方案3】:

要取模,你必须有 2^n-1 否则你会朝着不同的算法方向移动,有趣但不知何故是独立的方向,所以我建议你使用 big int 概念,因为它很容易......一个结构并以小值实现大值,例如

  struct bigint{
    int lowerbits;
    int upperbits;
  }

语句的分解也有像 2^n = (2^n-4 * 2^4 )-1%p 分解和单独处理它们的解决方案,那将是相当算法化的

【讨论】:

    【解决方案4】:

    要计算 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
    

    【讨论】:

      【解决方案5】:

      我在解决 HackerRank 上的一个数学问题时遇到了我在此处发布的答案,并且它适用于那里给出的所有给定测试用例。

      如果您将 np 限制为 64 位(无符号长整数)值,那么这里是数学方法:

      2^n - 1可以写成1*[ (2^n - 1)/(2 - 1) ]

      如果你仔细看,这是GP1 + 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

      所以,现在我们可以将上述关系应用于我们的全科医生,您就会得到答案!! 那是, (2^n - 1)%p 等价于 ( 1 + 2 + 4 + .. + 2^(n-1) )%p,现在应用给定的关系。

      【讨论】:

        【解决方案6】:

        首先,关注 2n 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 而不会溢出的乘法工具,那么您可以使用类似的算法,在每次平方运算后使用模数重复平方,然后取平方序列的乘积残差,每次乘法后再次取模。

        【讨论】:

          【解决方案7】:

          步骤 1. x= 将 1 移动 n 次,然后减去 1

          step 2.result = x 和 p 的逻辑与运算

          【讨论】:

          • 我认为问题不包含操作将执行哪种类型的数据。所以我只是谈了一个通用的解决方案。
          • 问题是这个不是通用的。移位和逻辑 and 是对位串而不是整数的操作。通用解决方案是那些做出较少假设的解决方案。
          • 移除了 x 的 int 数据类型。
          • 如果没有异国平台,它仍然不适用于 n > 62。此外,除非 p 也是整数 2^n-1,否则不会通过逻辑 AND 计算模数。
          • @ Potatoswatter,现在我得到了答案的限制。谢谢。为您的评论点赞。
          猜你喜欢
          • 2011-12-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-04
          • 2020-11-27
          • 2010-12-02
          相关资源
          最近更新 更多