主要用到二分的思想
ll mult(ll a, ll b, ll p) {
a %= p;
b %= p;
ll res = 0, tmp = a;
while(b) {
if (b & 1) {
res += tmp;
if (res > p) res -= p;
}
tmp <<= 1;
if (tmp > p) tmp -= p;
b >>= 1;
}
return res;
}
ll quick_pow(ll a, ll b, ll p) {
ll res = 1;
ll tmp = a % p;
while(b) {
if (b & 1) res = mult(res, tmp, p);
tmp = mult(tmp, tmp, p);
b >>= 1;
}
return res;
}
这里是当long long 级别的快速幂,乘法取模部分不能直接乘而应该手写快速乘
还有一种更快的版本
ll mult(ll x, ll y, ll p)
{
long double d=1;
d=d*x/p*y;
return ((x*y-((ll)d)*p)%p+p)%p;
}
ll quick_pow(ll a, ll b, ll p)
{
ll res = 1;
ll tmp = a % p;
while(b) {
if (b & 1) res = mult(res, tmp, p);
tmp = mult(tmp, tmp, p);
b >>= 1;
}
return res;
}
当幂次大到只能用字符串读取时,我们可以用一位一位的去乘。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<map>
#include<queue>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
char s[MAXN];
int a,mod,len;
ll mult(ll x,ll y,ll p)
{
long double d=1;
d=d*x/p*y;
return ((x*y-((ll)d)*p)%p+p)%p;
}
ll quick_pow(ll a,ll b,ll p)
{
a%=p; ll ret=1;
while(b)
{
if(b&1) ret=mult(ret,a,p);
a=mult(a,a,p); b>>=1;
}
return ret;
}
ll super_quick_pow(ll a,char *b,int len,int mod)
{
ll ret=1;
while(len>0)
{
ll x=b[len-1]-'0';
if(x)
{
ret=ret*quick_pow(a,x,mod);
}
a=quick_pow(a,10,mod);
len--;
}
return ret;
}
int main()
{
while(~scanf("%d%s%d",&a,s,&mod)) //读入a^s%mod,
{
len=strlen(s);
printf("%lld\n",super_quick_pow(a,s,len,mod));
}
return 0;
}
这样的复杂度有可能还是不能解决问题,这时候我们就要用的欧拉降幂进行处理。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<map>
#include<queue>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
char s[MAXN];
ll a,mod,len;
ll mult(ll x,ll y,ll p)
{
long double d=1;
d=d*x/p*y;
return ((x*y-((ll)d)*p)%p+p)%p;
}
ll quick_pow(ll a,ll b,ll p)
{
a%=p; ll ret=1;
while(b)
{
if(b&1) ret=mult(ret,a,p);
a=mult(a,a,p); b>>=1;
}
return ret;
}
ll super_quick_pow(ll a,char *b,int len,int mod)
{
ll ret=1;
while(len>0)
{
ll x=b[len-1]-'0';
if(x)
{
ret=ret*quick_pow(a,x,mod);
}
a=quick_pow(a,10,mod);
len--;
}
return ret;
}
ll phi(ll x)
{
ll ret=x;
for(ll i=2;i*i<=x;i++)
{
if(x%i==0)
{
ret=ret-ret/i;
while(x%i==0) x/=i;
}
if(x==1) break;
}
if(x>1) ret=ret-ret/t;
return ret;
}
int main()
{
while(~scanf("%lld%s%lld",&a,s,&mod)) //读入a^s%mod,
{
ll len=strlen(s);
ll p=phi(mod);
printf("phi[%d]=%d\n",mod,p);
ll t=0;
for(int i=0;i<len;i++)
{
t=(t*10+s[i]-'0')%p;
}
t+=p;
printf("%lld\n",quick_pow(a,t,mod));
}
return 0;
}