XidianOJ 1148 修理OJⅡ

--

快速幂加强版

网上有关的资料很少,好难找。。还是搜索水平不够

数论的题每次做都有一种好厉害的感觉

首先你需要知道φ(m),这是欧拉函数,表示小于m的整数中与m互质的个数

使用了广义欧拉定理

  a^b≡a^(b%φ(m)+φ(m))(mod m)   (b > φ(m) ) 

这样就大大降次了。

对于b < φ(m)的情况,直接使用快速幂计算,因为此时b很小

  

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
long long fast_mod(long long a,long long b,long long y){
    long long ans = 1;
    a = a % y;
    while (b > 0){
        if (b & 1)
            ans = (ans*a) % y;
        b = b / 2;
        a = (a*a) % y;
    }
    return ans;
}
long long eular(long long n){
    long long res = 1;
    long long p = 2;
    while (p*p <= n){
        if (n % p == 0){
            res*= (p-1);
            n /= p;
            while (n % p == 0){
                res *= p;
                n/=p;
            }
        }
        p++;
    }
    if (n!=1){
        res*=(n-1);
    }
    return res;
}

long long gcd(long long a,long long b){
    if (a < b) return gcd(b,a);
    if (b == 0) return a;
    else return gcd(b,a%b);
} 

long long power(long b,long c){
    if (c == 1) return b;
    long long res = power(b,c/2);
    if (c % 2 == 0)
        return res*res;
    else 
        return res*res*b;
}

long long solve(long long a,long long b,long long c,long long y){
    long long fai = eular(y); 
    if (log(fai)/log(b) < c)
        return fast_mod(a,fast_mod(b,c,fai)+fai,y);
    else 
        return fast_mod(a,power(b,c),y);
}

int main(){
    long long a,b,c,y; 
     while (scanf("%lld %lld %lld %lld",&a,&b,&c,&y) != EOF){
        printf("%lld
",solve(a,b,c,y));
        //printf("%lld
",power(b,c));
    }
    return 0;
} 

参考资料: 

  http://blog.csdn.net/guhaiteng/article/details/52588223

原文地址:https://www.cnblogs.com/ToTOrz/p/6104054.html