C++ 计算(a^b)%c,其中0<=a、 b、c<=10^18
如何计算C++ 计算(a^b)%c,其中0<=a、 b、c<=10^18,c++,math,modular-arithmetic,C++,Math,Modular Arithmetic,如何计算(a^b)%c,其中0我在c++中使用此代码: 长电源(长a、长b、长c) { 如果(b==0) { 返回1; } 如果(b%2==0) { 长w=功率(a,b/2,c); 返回值(w*w)%c; } 其他的 { int w=功率(a,b-1,c); 返回(a*w)%c; } } 它具有对数复杂性。您遇到了temp*temp(长溢出)问题。您可以使用快速模幂算法将它们乘以模m来忽略此问题。这里有工作代码: unsigned long long bigMultiply(unsigned
(a^b)%c
,其中0我在c++中使用此代码:
长电源(长a、长b、长c)
{
如果(b==0)
{
返回1;
}
如果(b%2==0)
{
长w=功率(a,b/2,c);
返回值(w*w)%c;
}
其他的
{
int w=功率(a,b-1,c);
返回(a*w)%c;
}
}
它具有对数复杂性。您遇到了temp*temp(长溢出)问题。您可以使用快速模幂算法将它们乘以模m来忽略此问题。这里有工作代码:
unsigned long long bigMultiply(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(p == 0 )return b;
if(p%2 == 0)
{
unsigned long long temp = bigMultiply(b,p/2ll,m);
return ((temp)+(temp))%m;
}
else
return (b + bigMultiply(b,p-1,m))%m;
}
unsigned long long bigMod(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(b == 1)
return b;
if(p == 0 )return 1;
if( p == 1)return b;
if(p%2 == 0)
{
unsigned ll temp = bigMod(b,p/2ll,m);
return bigMultiply(temp,temp,m);
}
else
return (b * bigMod(b,p-1,m))%m;
}
这可能是一个有用的起点。如果你观察到,(a**b)%c==((a%c)**b)%c)
,那么向公式中添加模数并不难。可能的重复。我正在尝试((a%m)*(b%m))%m,但可能是我的方法不对。@abuhani的可能重复方法((a%m)^(b%m)%m失败,因为指数必须由φ(m)进行模数化,其中phi是Euler的toticent函数。如果m是素数,那么phi(m)=m-1,您可以将其减少为((a%m)^(b%(m-1))%m。如果a和b都是64位,则不起作用,因为w*w
需要一个128位类型来存储某些角情况下的故障:bigMod(1,p,1)
是1,应该是0。建议If(b==1)返回b%m;
类似于if(p==0)返回1;
-->if(p==0)返回1%m;
处理m==1
和if(p==1)返回b;
if(p==1)返回b%m;
处理b>=m
。我非常肯定b*bigMod(b,p-1,m)
很容易溢出。除此之外,此代码非常好,但也有一些限制:(temp)+(temp)
在m>ULLONG_MAX/2
时仍然会溢出,但这超出了OP的c
a = 12345 b = 123456789 and c = 123456789012345
59212459031520
unsigned long long bigMultiply(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(p == 0 )return b;
if(p%2 == 0)
{
unsigned long long temp = bigMultiply(b,p/2ll,m);
return ((temp)+(temp))%m;
}
else
return (b + bigMultiply(b,p-1,m))%m;
}
unsigned long long bigMod(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(b == 1)
return b;
if(p == 0 )return 1;
if( p == 1)return b;
if(p%2 == 0)
{
unsigned ll temp = bigMod(b,p/2ll,m);
return bigMultiply(temp,temp,m);
}
else
return (b * bigMod(b,p-1,m))%m;
}