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;
}