查找(num *(pow(b,p)-1)/ den)%mod其中p非常大(10 ^ 18)

时间:2019-06-25 07:17:05

标签: binary exponentiation

我想找到(num *(pow(b,p)-1)/ den)%mod。我知道二进制求幂。但是我们不能直接做到这一点。保证分子可被分母整除。这意味着

[num *(pow(b,p)-1)]%den == 0

对mod的约束是1 <= mod <= 10 ^ 9,并且mod可能是素数或复合

对b的约束:1 <= b <= 10

对p的约束:1 <= p <=(10 ^ 18)

限制num:1 <= num <=(10 ^ 9)

对den的约束:1 <= den <=(10 ^ 9)

这里pow(b,p)表示b升为幂p(b ^ p)。保证分子可被分母整除。我该如何使用二进制幂运算

1 个答案:

答案 0 :(得分:1)

您的表达式应重写为简化形式。首先让k = num / den,根据您的问题为k整数。

所以您必须计算
(k×(b ^ p-1))mod m =((k mod m)×((b ^ p -1)mod m))mod m
=((k mod m)×((b ^ p mod m)-1 mod m)mod m)mod m
=(((k mod m)×((b ^ p mod m)+ m-1)mod m)mod m(1)

所以真正的问题是计算b ^ p mod m

许多语言(python,java等)在其标准库中已经具有模块化指数。请查阅文档并使用它。否则,这是一个C实现。

unsigned long long modexp(unsigned long long b, unsigned long long e, unsigned long long m) {
  if (m==1) return 0;
  unsigned long long res=1;
  unsigned long long bb = b % m;
  while (e) {
    if (e & 1) 
      res = (res*b) % m;
    e >>= 1;
    bb = (bb*bb) % m;
  }
  return res;
}

该实现使用long long来满足您的约束。它依赖于二进制求幂的经典技巧。计算所有b ^ l的值,其中l是2的幂(l = 2 ^ t)并将其存储在var bb中,如果e的对应的t th 位置1,则该值b ^ l被集成到结果中。通过检查e的连续奇偶校验来完成位测试,同时在每一步向右移动e。

最后,(a×b)mod m =((a mod m)×(b mod m))mod m的事实用于避免对非常大的数进行计算。我们总是有res

然后,您只需应用(1)即可获得最终结果。

根据注释中给出的精度进行编辑
要计算n =(3 ^ p-1)/ 2 mod m,可以指出
(3 ^ p-1)/ 2 = x * m + n(因为3 ^ p-1是偶数,x是整数,0≤n 3 ^ p-1 = x * 2 * m + 2n(0≤2n<2m)
所以2n =(3 ^ p-1)mod 2m

我们可以仅以2 * m的模数应用前面的方法,然后将结果(将是偶数)除以2。