题目描述
给你三个整数 a,b,p求 a b a^b ab mod p p p
输入格式
输入只有一行三个整数,分别代表 a,b,pa,b,p。
输出格式
输出一行一个字符串 a b a^b ab mod p p p =s,其中 a,b,p 分别为题目给定的值, s为运算结果。
输入输出样例
输入
2 10 9
输出
2^10 mod 9=7
说明/提示
样例解释
2
10
2^{10}
210 = 1024
1024 mod 9 = 7
数据规模与约定
对于 100% 的数据,保证 0 < = a , b < 2 31 0<=a,b < 2^{31} 0<=a,b<231 ,a+b>0, 2 < = p < 2 31 2<=p< 2^{31} 2<=p<231
快速幂
快速幂算法是建立在二进制的按权展开求和的方法的基础上的,在二进制中我们先将二迸制的数写成加权系数展开式,而后根据十进制的加法规则进行求和得到原来的数,如10 二进制码为1010
可由
0
∗
2
0
+
1
∗
2
1
+
0
∗
2
2
+
1
∗
2
3
0 * 2^ 0+1 * 2 ^1 +0 * 2 ^2+1 * 2 ^3
0∗20+1∗21+0∗22+1∗23
得到,我们通过思考将其和我们的幂的运算进行结合,便可得到一下式子:
3
(
0
∗
2
0
+
1
∗
2
1
+
0
∗
2
2
+
1
∗
2
3
)
3^ {(0 * 2^ 0 + 1 * 2^ 1 + 0 * 2^ 2 + 1 * 2^ 3)}
3(0∗20+1∗21+0∗22+1∗23)
这时我们发现循环次数减少了一半多,指数系数为0可以不运算。最终我们可以得到以下式子:
3
(
2
1
+
2
3
)
3^ {(2^ 1+2^3)}
3(21+23)=
3
2
1
∗
3
2
3
3^{2^1}*3^{2^3}
321∗323
同底数密相乘,底数不变,指数相加
int quick_pow(int a,int n)
{
int ans=1;
int base=a;
//n代表指数,对其一边进行二进制转化,一边计算
while (n>0)
{
//低位开始的二进制转化,如果此位当前是1
if(n%2==1)
ans=ans*base;
//每一位都进行一次乘积
base=base*base;
n=n/2;
}
return ans;
}
快速幂的模运算
(
a
∗
b
)
m
o
d
c
=
(
(
a
m
o
d
c
)
∗
(
b
m
o
d
c
)
)
m
o
d
c
(a * b) \mod c =((a \mod c)*(b \mod c)) \mod c
(a∗b)modc=((amodc)∗(bmodc))modc
再而推导出后面公式:
(
a
b
)
m
o
d
c
=
(
a
m
o
d
c
)
b
m
o
d
c
(a^b) \mod c =(a \mod c)^b \mod c
(ab)modc=(amodc)bmodc
#include<bits/c++io.h>
#include<iostream>
#define ll long long
using namespace std;
ll quick_pow(ll a,ll n,ll mod)
{
ll ans=1,base=a%mod;
while (n>0)
{
if(n%2==1)
ans=(ans*base)%mod;
base=(base*base)%mod;
n=n/2;
}
ans=ans%mod;
return ans;
}
int main()
{
ll a,n,mod;
cin>>a>>n>>mod;
printf("%ld^%ld mod %ld=%ld",a,n,mod,quick_pow(a,n,mod));
return 0;
}