C++ 计算(a^b)%MOD

C++ 计算(a^b)%MOD,c++,math,C++,Math,我想编写代码来计算pow(a,b)%MOD的值。我用C++来编写代码。 但问题是b的值可能非常大。我知道log(b)时间复杂度方法。但是,B的值可能不适合C++的“长隆”数据类型。例如,b可以是第100000000个斐波那契数。精确计算如此大的数字本身是不可能的(在时间限制内) 附言: pow(a,b)指a*a*a*a*。。。b次 X%MOD表示将X除以MOD得到的余数 首先:^在C/C++中不是powers的操作符。事实上,这方面没有操作员^表示按位异或。您必须使用pow(base,exp)

我想编写代码来计算pow(a,b)%MOD的值。我用C++来编写代码。 但问题是b的值可能非常大。我知道log(b)时间复杂度方法。但是,B的值可能不适合C++的“长隆”数据类型。例如,b可以是第100000000个斐波那契数。精确计算如此大的数字本身是不可能的(在时间限制内)

附言:

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

首先:
^
在C/C++中不是powers的操作符。事实上,这方面没有操作员<代码>^表示按位异或。您必须使用
pow(base,exp)
,它可以在标题
math.h
cmath
中找到


对于如此巨大的数字,使用
double
longdouble
(确切的长度和生成的数据类型可能因平台而异),但有时您会遇到精度问题,因此根据您的使用情况,您的最佳选择可能是使用自定义数据类型(编辑:例如,从一个链接问题中找到的一个库中).

我建议使用一个专门的数学库。另外,这看起来像加密,所以我建议使用加密库。GNU肯定有一个可以使用的库。这是因为在加密中,在许多情况下,指数可能会被选择,以便使用普通数学库无法采用的快捷方式进行高效计算。

这是一个典型的ta请(或者说,真的,请!)读一下这本书

然后是

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

在我年轻的时候,我们手工制作了这样的样本:)即使数字远远超出了32/64位的范围

编辑:好吧,你生活和学习。2008年的结果是:

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

因此,计算φ(b)不需要知道它的因子

编辑(2):


这就是你需要计算的,以得到任何a,b和MOD的正确答案。

要处理非常大的数字,请查看库。它有一个powm()函数,可以很好地实现这一目的

发件人:


我用这个函数来解决这个问题

UVA 374-大模式

<>但是,B的值可能不适合C++的“长隆”数据类型。例如,b可以是第100000000个斐波那契数

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

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

您可以使用与计算斐波那契数相同的递归来计算您询问的特定乘积——您根本不需要大数或模幂运算

有时会出现的另一个版本是

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


可能的重复只是为了澄清,C++中的代码> ^ /COD>是XOR运算符,而不是指数运算符(你会得到一些相当不错的结果,第一手经验)。我相信你必须使用<代码>数学> .EXP(A,B)< /C> > NBROOKS:虽然你确实正确,C++使用了代码> ^ < /C> >表示XOR,<代码> Max.EXP(A,B)< /C> >看起来不象C++(基于这个名字,我希望它能计算指数,而不是把一个数提升到一个幂)。至少可以说,暴力手段不是解决问题的最佳方式。一点数字理论101,你知道经典的欧拉定理。我的答案有适当的联系。我相信MOD是一个普通的整数,它适合于CPU的寄存器,这使得这个任务在模块算术中是一个简单的练习。它的可能重复是一个数论问题,真的。这里不需要暴力。这项任务的全部目的是展示一些简单经典定理的优越性。看看我的答案。有趣的是,我猜你刚刚偷走了我周末的空闲时间,打算好好读一读。:)这本书很好:伊万·维诺格拉多夫的书也很好。Jean-Pierre Serre的“算术课程”开启了更多的可能性。谢谢Viktor。我得到了想要的。谢谢你的帮助…:-)顺便说一句,我知道托蒂函数,但不知道欧拉定理……“所以计算φ(b)不需要知道它的因子。”不过,这看起来不像是计算
phi(b)
的实用方法。@MarkDickinson:是的,这就是为什么我在Schramm的论文中添加了注释。这里只涉及一个离散傅里叶变换;这就是我的意思:通过傅里叶变换进行计算不会比通过因子分解进行计算更有效。(顺便说一句,我相信维基百科上Schramm的研究结果实际上要古老得多。)我也相信Schramm的研究结果可能早就为人所知了。关于傅立叶的事情。。。是的,我看到了我答案的弱点。不幸的是,他不是一个数字理论家。小调:失败的角落案例:
restOfPot(a,0,1)
,可以用
long R=1%T修复
template <class Integer>
Integer powm(const Integer& b, const Integer& p, const Integer& 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
// 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);
}