Calculating (a^b)%MOD
我想编写代码以计算pow(a,b)%MOD的值。 我使用C ++进行编码。
但是问题是b的值可能非常大。 我知道log(b)时间复杂度方法。 但是,b的值可能不适合C ++的数据类型" long long"。 例如,b可以是第1000000000个斐波那契数。 如此大的数字本身无法精确计算(在时限内)。
附言 :
- pow(a,b)表示a * a * a * a * ... b次。
- X%MOD是指将X除以MOD获得的余数。
这是典型的任务。请(或者,实际上,请!)阅读有关Euler的totient函数的信息。
然后是欧拉定理。
问题是您可以将a ^ b大大减少到a ^(b%phi(MOD))。是的,您将需要某种整数分解方法,但是仍然没有关于实际计算所需功效的疯狂想法。
我们在青年时期就手工进行过此类采样:)即使数字远远超出了32/64位范围。
编辑:恩,你生活和学习。在2008年获得了以下结果:
" Totient是gcd的离散傅立叶变换:(Schramm(2008))"
因此,计算phi(b)不需要知道其因素。
编辑(2):
Carmichael函数是您需要计算的函数,以便为任何a,b和MOD获得正确的答案。
我用这个功能解决这个问题
UVA 374-大模组
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=310
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 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); } |
要处理非常大的数字,请查看boost的Multiprecision库。它具有一个powm()函数,可以很好地实现此目的。
来自通用整数运算:
1
2 template <class Integer>
Integer powm(const Integer& b, const Integer& p, const Integer& m);Returns bp % m.
例:
1 2 3 4 5 6 7 8 9 | #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; |
印刷品:
1 | result is: 5758534182572671080415167723795472693 |
But, the value of b might not fit in the data type"long long" of C++. For example b can be 1000000000 th Fibonacci number.
对于这样的事情,有一个简单的解决方法:回想
a^(b+c) == a^b * a^c mod d
您可以使用与计算斐波那契数相同的递归来计算所要的特定产品-完全不需要大数或模幂!
有时会出现另一个版本
a^(b*c) = (a^b)^c mod d
我建议使用专门的数学库。而且这看起来像加密货币,所以我建议使用加密货币库。 GNU一定有一个您可以使用的。这是因为在很多情况下,可以使用常规数学库无法假定的快捷方式来选择指数,以进行有效的计算,从而达到加密效果。
首先:C / C ++中的
对于如此巨大的数字,请使用