处理何种问题:在处理 a^b mod c 的问题中,如果遇到b的值极大,大到只能用字符串来存取时,普通的快速幂已经无法处理该问题时,就该用到欧拉降幂来处理了。
性能:可以将时间复杂度降至快速幂的水平。
原理: a^b mod c == a^(b mod phi(c)+phi(c)) mod c
(PS: phi(x) 为欧拉函数);其核心就是将大数 b 降至为一个long long 级别的数。
实现步骤:在计算 时的处理方式
int len=strlen(b);
long long ola=PHI(mod); // phi(c) 的值为ola
long long n=0;
for(int i=0;i<len;++i)
{
n=(n*10+b[i]-'0')%ola;
}
备注:若题目中给的出的b需要处理一下才是才行,比如给出一个b,但是需要求的是(b-1)的时候,在这里并不需要再加一个大数减法,只需要用加个减法取模就行了。
输入样例解释:
2 3 10007 // a的b次方对c取模
5 15555555555555555555555555555555 2666
5555 9999999999999999999999999999999999999999999999999 100005
输出样例解释:
8
1427
79370
//没文化真可怕,一个n的10的100000次方的次方天真的要用大数加快速幂去做,天真 //。。。。现在终于知道了,这就是超级快速幂,遇到这种题,需要用到欧拉降幂,。。。无知的我 //公式:a^b mod c == a^(b mod phi(c)+phi(c)) mod c (phi 为 欧拉函数) //这种题目一般比较适合 b 特别大的情况下,大到 b 只能用字符串来存取了 #include<iostream> #include<algorithm> #include<string> #include<cmath> #include<cstdio> using namespace std; const int MaxN=1000100; long long fpow(long long a,long long n,long long mod) { long long Ans=1; a=a%mod; while(n!=0) { if(n&1) Ans=(Ans*a)%mod; n>>=1; a=(a*a)%mod; } return Ans; } long long PHI(long long x) { long long ans = x; for(long long i = 2; i*i <= x; i++) { if(x % i == 0) { ans = ans / i * (i-1); while(x % i == 0) x /= i; } } if(x > 1) ans = ans / x * (x-1); return ans; } long long o_fpow(long long a,char b[],long long mod) { int len=strlen(b); long long ola=PHI(mod); long long n=0; for(int i=0;i<len;++i) { n=(n*10+b[i]-'0')%ola; } n+=ola; return fpow(a,n,mod); } int main() { long long a,mod; char b[MaxN]; while(~scanf("%lld%s%lld",&a,b,&mod))// a 的 b 次方对mod取模 { printf("%lld ",o_fpow(a,b,mod)); } return 0; }