简体   繁体   English

C ++:如何计算升到大数的模数?

[英]C++ : How to calculate modulo of a number raised to large power?

I am solving a programming problem where I have to print the answer in the format answer mod 10 ^ 9 + 7, where 'answer' is the actual answer to the problem. 我正在解决一个编程问题,我必须以答案mod 10 ^ 9 + 7的格式打印答案,其中“答案”是问题的实际答案。

I have figured out the algorithm to solve the problem, however the caveat is that the answer to the problem is always of the format m * 10 ^ n, where 我已经找到解决问题的算法,但是需要注意的是,问题的答案始终是格式m * 10 ^ n,其中

1 <= m <= 8 and 2 <= n <= 10 ^ 18, that is in the answer 10 can be raised to a power as large as 10 ^ 18. Ofcourse, directly calculating 10 ^ n may overflow. 1 <= m <= 8和2 <= n <= 10 ^ 18,也就是说,答案10可以提高到10 ^ 18的幂。当然,直接计算10 ^ n可能会溢出。

What should I do next? 接下来我该怎么办?

Evaluating 10^n mod M : 评估10^n mod M

What you need is Modular Exponentiation . 您需要的是模幂 It can compute (a^b)%m in log_2(b) (log base 2). 它可以计算log_2(b) (a^b)%m (对数为2)。

Example

Let's say you need to compute 10^9 . 假设您需要计算10^9

  1. One way is you sequentially multiple 10 , 9 times. 一种方法是你依次多个109倍。
  2. Or, use divide and conquer approach. 或者,使用分而治之的方法。

    10^9 = (10^8)*(10^1)

    10^8 = (10^4)*(10^4) : Do you need to compute 10^4 twice? 10^8 = (10^4)*(10^4) :是否需要两次计算10^4

    10^4 = (10^2)*(10^2) : Do you need to compute 10^2 twice? 10^4 = (10^2)*(10^2) :是否需要两次计算10^2

    10^2 = (10^1)*(10^1)

    10^1 = (10^1)*(10^0)

    10^0 is the base case. 10^0是基本情况。

    So, what we basically do is: 因此,我们基本上要做的是:

    1. If power is an odd number, then we compute base^(power-1) and multiply it with base to get base^power . 如果power是一个奇数,则我们计算base^(power-1)并将其乘以base得到base^power [ base^power = (base^(power-1)) * base) ] [ base^power = (base^(power-1)) * base) ]
    2. If power is an even number, then we compute base^(power/2) and multiply it with itself to get base^power . 如果power是偶数,则我们计算base^(power/2)并将其与自身相乘以获得base^power [ base^power = (base^(power/2)) * (base^(power/2)) ]. [ base^power = (base^(power/2)) * (base^(power/2)) ]。 But we compute base^(power/2) only once. 但是我们只计算一次base^(power/2)

Computational Complexity : 计算复杂度

As stated here : 如前所述这里

A brief analysis shows that such an algorithm uses floor(log_2(n)) squarings and at most floor(log_2(n)) multiplications. 简要分析表明,这种算法使用floor(log_2(n))平方,最多使用floor(log_2(n))乘法。 More precisely, the number of multiplications is one less than the number of ones present in the binary expansion of n. 更准确地说,乘法的数量比n的二进制展开式中存在的乘法数量少1。

So, we can say that the runtime is of the order of log_2(n) . 因此,可以说运行时log_2(n) ( O(log_2(power)) ) O(log_2(power))

Evaluating the modulo part: 评估模数部分:

It is easy to notice that while computing a value as large as 10^(10^18) , we are bound to overflow even largest of the primitive types ( long long int ). 很容易注意到,当计算一个最大为10^(10^18) ,我们必然会溢出甚至最大的原始类型( long long int )。 And here enters the Modular Multiplication , according to which (a * b) % c = ((a % c) * (b % c)) % c . 然后进入模乘 ,根据(a * b) % c = ((a % c) * (b % c)) % c As a side note, you might not see this rule in use when you directly look at code, but it is being used if you evalute the recursive calls. 附带说明,当您直接查看代码时,您可能看不到该规则在使用中,但是如果您评估递归调用,则会使用该规则。

Problem solved? 问题解决了?

We prevent overflow by computing the modulo on the run. 我们通过计算运行中的模数来防止溢出。 Say, if we got some value as 10^9 and we need to multiply it with itself. 假设,如果我们得到一些值为10^9值,则需要将其与自身相乘。 Overflow? 溢出? Nah, not this time. 不,这次不行。

ans = ((10^9 % 1000000007) * (10^9 % 1000000007)) % 1000000007
ans = 10^18 % 1000000007
ans = 49

Code: 码:

While there are multiple implementations, here is a simple one: 虽然有多种实现,但这是一个简单的实现:

const int M = 1e9 + 7;
long long int powxy(long long int x, long long int y) {
    if (y == 0) return 1;
    if (y%2 == 1) return (x*powxy(x, y-1))%M;
    long long int t = powxy(x, y/2);
    return (t*t)%M;
}

Tested here . 在这里测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM