欧拉降幂

欧拉降幂

处理何种问题:在处理 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\n",o_fpow(a,b,mod));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/l1l1/p/9658131.html