计算(a ^ b)%MOD

时间:2012-06-30 07:48:54

标签: c++ math

我想编码用于计算pow(a,b)%MOD的值。我用C ++编写代码。

但问题是b的值可能非常大。我知道log(b)时间复杂度方法。但是,b的值可能不适合C ++的“long long”数据类型。例如,b可以是1000000000个斐波那契数。这样一个大数字的精确计算本身是不可能的(在时间限制内)。

P.S。 :

  • pow(a,b)表示a * a * a * a * ... b次。
  • X%MOD表示通过MOD除以X得到的余数。

7 个答案:

答案 0 :(得分:12)

这是一项典型的任务。请(或者,真的,请!)阅读Euler's totient function

然后是Euler's theorem

事情是你可以大大减少a ^ b到^(b%phi(MOD))。是的,你需要某种整数分解方法,但仍然没有关于实际计算所需功率的疯狂想法。

我年轻时手工制作了这样的样品:)即使数字远远超过32/64位范围。

编辑:嗯,你生活和学习。 2008年获得了结果:

“总数是gcd的离散傅里叶变换:( Schramm(2008))”

因此,要计算phi(b),不需要知道它的因素。

EDIT(2):

Carmichael's function是您需要计算以获得任何a,b和MOD的正确答案。

答案 1 :(得分:1)

要处理非常大的数字,请查看boost's Multiprecision库。它有一个powm()函数,可以很好地用于此目的。

来自Generic Integer Operations

template <class Integer>
Integer powm(const Integer& b, const Integer& p, const Integer& m);
     

返回b p %m。

示例:

#include <boost/multiprecision/cpp_int.hpp>

boost::multiprecision::cpp_int pow("8912627233012800753578052027888001981");
boost::multiprecision::cpp_int mod("0x86f71688cdd2612c117d1f54bdae029");
boost::multiprecision::cpp_int base(12345);

boost::multiprecision::cpp_int result = powm(base, pow, mod);

std::cout << "result is: " << result << std::endl;

打印:

result is: 5758534182572671080415167723795472693

答案 2 :(得分:1)

我使用此功能来解决此问题

UVA 374 - Big Mod

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=310

// a^b % T

// with Exponentiation by squaring (http://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method)

// if a very large use
// R=(unsigned long long)(R*a)%T;

int restOfPot(long long a,int b,int T)
{
    a%=T;
    long long R=1;

    while(b)
    {
        if(b&1) R=(R*a)%T;
        a=(a*a)%T;
        b>>=1;
    }

    return int(R);
}

答案 3 :(得分:0)

首先:C / C ++中的^ 是权力的运算符。事实上,没有这方面的运营商。 ^表示按位 XOR 。您必须使用标题pow(base, exp)math.h中的cmath

对于如此庞大的数字,使用doublelong double(确切的长度和结果数据类型可能因您的平台而异),但在某些时候您会偶然发现精度问题,因此取决于您的用例,您最好的选择可能是使用自定义数据类型的值的大小(编辑:例如,从其中一个链接问题中找到的库之一)。

答案 4 :(得分:0)

我建议使用专门的数学库。这看起来像加密,所以我建议使用加密库。 GNU必然会有一个你可以使用的。这是因为在加密中,在很多情况下,可以选择指数以使用普通数学库无法假设的快捷方式进行有效计算。

答案 5 :(得分:0)

  

但是,b的值可能不适合C ++的“long long”数据类型。例如,b可以是1000000000个斐波纳契数。

对于这样的事情,有一个简单的解决方法:召回

  

a ^(b + c)== a ^ b * a ^ c mod d

您可以使用用于计算斐波纳契数的相同类型的递归计算您询问的特定产品 - 您根本不需要大数或模幂运算!

有时出现的另一个版本是

  

a ^(b * c)=(a ^ b)^ c mod d

答案 6 :(得分:0)

#include<bits/stdc++.h>
using namespace std;

#define mod 1000000007
#define ll long long

ll power(ll x, ll y)
{
    if ( y == 0)
        return 1;
    ll temp = power(x, y / 2);
    if (y % 2 == 0)
        return (temp * temp) % mod;
    else
        return (((temp * temp) % mod) * x) % mod;
}
ll dmod(ll x)
{  
    return ((x + mod) % mod);
}

ll modular_power(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)ans = dmod(ans * x);
        y /= 2;
        x = dmod(x * x);
    }
    return ans;
}

int main()
{ 
    ll a, b;
    cin >> a >> b;
    ll ans1 = modular_power(a, b);
    ll ans2 = power(a, b);
    //  both answers are same
    cout << ans1 << " " << ans2 ;
}