博客原文地址:http://blog.youkuaiyun.com/xuechelingxiao/article/details/38614491
对于一般的求a^b%c的值,当a,b都在long long范围内,c在1e9的时候,都可以用快速幂取模进行求解。
LL powerMod(LL x, LL k, LL m){
LL res = 1;
while(x %= m, k){
if(k&1) res *= x, res %= m;
x *= x, k >>=1;
}
return res;
}
题目大意:题意很简单,就是求a^b%c的结果,只是a,b,c的范围是 (1<=a,b,c<2^63)。
思路:这个题最关键的问题是在快速幂的时候,由于a的最大值是2^63-1,所以会出现乘法溢出,这也是最容易WA的地方。
要解决这个问题,就需要将乘法转换成加法,进行“快速乘”(暂且这么叫吧,我也不知道叫啥-。-),就是代码中的multiplyMod,接下来就没什么问题了。
#include <stdio.h>
#include <iostream>
#define ULL long long
using namespace std;
ULL n, m, mod;
ULL multiplyMod(ULL x, ULL k, ULL m){
ULL res = 0;
x %= m;
while(k){
if(k&1){
res += x;
if(res >= m)
res -= m;
}
x += x;
if(x >= m){
x -= m;
}
k >>=1;
}
return res;
}
ULL powerMod(ULL x, ULL k, ULL m){
ULL res = 1;
while(k){
if(k&1){
res = multiplyMod(res, x, m);
}
x = multiplyMod(x, x, m), k >>=1;
}
return res;
}
int main()
{
while(~scanf("%I64d%I64d%I64d", &n, &m, &mod)){
printf("%I64d\n", powerMod(n, m, mod));
}
return 0;
}
题目大意:一样的求a^b%c的结果,只是b的范围变得很大了, (1<=A,C<=1000000000,1<=B<=10^1000000)。
思路:对于这个问题,就需要用到一个公式
A^x = A^(x % Phi(C) + Phi(C)) (mod C)
对于这个公式,可以给出两个证明的博客,一个是aekdycoin大犇的证明:http://www.narutoacm.com/archives/a-pow-b-mod-m/
另一个是 http://www.narutoacm.com/archives/a-pow-b-mod-m/
有了理论支持,这个题也就不是什么问题了,代码如下。
#include <stdio.h>
#include <string.h>
#define LL long long
int eular(int n){
int ret = 1;
for(int i = 2; i*i <= n;i++)
if(n%i == 0){
n /= i, ret *= i-1;
while(n%i == 0)
n /= i, ret *= i;
}
if(n > 1)
ret *= n-1;
return ret;
}
LL powerMod(LL x, LL k, LL m){
LL res = 1;
while(x %= m, k){
if(k&1) res *= x, res %= m;
x *= x, k >>=1;
}
return res;
}
LL n, mod;
char m[1000005];
int main()
{
while(~scanf("%I64d%s%I64d", &n, m, &mod)){
LL phi = eular(mod);
int len = strlen(m);
LL num = 0;
for(int i = 0; i < len; ++i){
if(len >= 10){
num = (num*10+(m[i]-'0'))%phi + phi;
}
else {
num = num*10+(m[i]-'0');
}
}
printf("%I64d\n", powerMod(n, num, mod));
}
return 0;
}