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

C 计算((2^n)-1)mod p的最佳方法,c,primes,modulo,C,Primes,Modulo,我正在做一个加密练习,我试图计算(2n-1)mod p,其中p是一个素数 这样做的最佳方法是什么?我用的是C,所以当n较大时,2n-1变得太大而无法容纳 我遇到了方程(a*b)modp=(a(bmodp))modp,但我不确定这是否适用于这种情况,因为2n-1可能是素数(或者我不确定如何将其分解) 非常感谢您的帮助。步骤1。x=移动1 n次,然后减去1 步骤2.result=x和p的逻辑and运算要取模,你必须有2^n-1,否则你将朝不同的算法方向移动,有趣但方向不同,因此我建议你使用大整数概念

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

这样做的最佳方法是什么?我用的是C,所以当n较大时,2n-1变得太大而无法容纳

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


非常感谢您的帮助。

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


步骤2.result=x和p的逻辑and运算

要取模,你必须有2^n-1,否则你将朝不同的算法方向移动,有趣但方向不同,因此我建议你使用大整数概念,因为这很容易。。。建立一个结构并在小值中实现大值,例如

  struct bigint{
    int lowerbits;
    int upperbits;
  }

语句的分解也有类似于2^n=(2^n-4*2^4)-1%p分解并分别处理它们,这将是非常算法化的,然后提供一些提示来帮助您找到更好的方法:

  • 不要用(a*b)modp=(a(bmodp))modp来计算2n-1模p,用它来计算2n模p,然后再减去
  • 在这里可能有用。这样,你实际需要处理的指数就不会超过p

  • 要计算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
    
    首先,关注2n模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而不产生溢出,那么您可以使用一个类似的算法,在每次平方运算后使用模反复平方,然后取平方残差序列的乘积,在每次乘法后再次使用模。

    您在注释中提到
    n
    p
    是9或10位数字或其他数字。如果将它们限制为32位(
    无符号长
    )值,则可以通过简单(二进制)模幂运算找到
    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< /代码>

    由于'common residence'或'resident'
    (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;
    

    当我在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

    如果您对上述关系是否正确有疑问,您可以在谷歌上搜索,也可以查看此链接:

    因此,现在我们可以将上述关系应用于我们的GP,您将得到您的答案!! 就是,
    (2^n-1)%p
    相当于
    (1+2+4+..+2^(n-1))%p
    ,现在应用给定的关系

    我更喜欢你在我的博客上的帖子,回答得很好,但我怎么能“事后减去”?因为mod可能在其中一个步骤中发生变化。例如,(100mod100)=0,而(100-1)mod100=(99mod100)=99。之后的减法是如何工作的呢?好吧,除非p=2,否则2^n mod p不会是0。(但在一般情况下,你可以测试一下)@navinpai:-1 mod 100=99。我认为这个问题不包括操作将在哪种类型的数据上进行。所以我只是想找到一个通用的解决方案。问题是这不是通用的。移位和逻辑and是位字符串上的操作,而不是整数。一般的解决方案是那些假设较少的解决方案。删除了x的int数据类型。如果没有外来平台,它仍然不适用于n>62。此外,模不是通过逻辑AND计算的,除非p也是一个整数2^n-1。@Potatoswatter,现在我得到了我答案的限制。谢谢对你的评论投赞成票。n和p的数字范围非常相关。p是一个10位数的素数(比如100000007),n最多是9位数。是否有任何10位数的素数达到99999999,或者有一个特定的上限?2^32 ≈ 4*10^9是10位数字,所以问题是你是否可以在不溢出本机64位整数类型的情况下对小于p的任何数字进行平方运算。我可以选择我的素数,比如说,我选择它作为100000007(前10位素数)谢谢。这很有效。但是你能解释一下最后一行吗?我不知道那是什么doing@navinpai-是-我会更新答案的。