2019 ICPC 南京站网络赛 super_log

广义欧拉降幂,在a与m不互质的时候要特判a的b-1指数塔和phi[m]的关系。
不知道是数据水还是有计算因素的影响,很多假算法也可以通过……

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef long long ll;

const int maxn = 1e6+5;

int cnt;
int pri[maxn];
int phi[maxn];
bool is[maxn];

void init () {
    is[0] = is[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!is[i]) {
            pri[++cnt] = i;
            phi[i] = i-1;
        }
        for (int j = 1; j <= cnt && 1ll*i*pri[j] < maxn; ++j) {
            is[i*pri[j]] = 1;
            if (i % pri[j] == 0) {
                phi[i*pri[j]] = phi[i]*pri[j];
                break;
            }
            else {
                phi[i*pri[j]] = phi[i]*(pri[j]-1);
            }
        }
    }
}

ll qm (ll a, ll b, ll p) {
    ll res = 1;
    a %= p;
    while (b) {
        if (b&1) {
            res = res*a%p;
        }
        a = a*a%p;
        b >>= 1;
    }
    return res;
}

bool check (ll a, ll b, ll p) {
    ll res = 1;
    if (a >= p) {
        return 0;
    }
    for (int i = 1; i <= b; ++i) {
        if (res >= 20) {
            return 0;
        }
        res = qm(a, res, 1e18);
        if (res >= p) {
            return 0;
        }
    }
    return 1;
}

ll gcd (ll a, ll b) {
    if (b == 0) {
        return a;
    }
    return gcd(b, a%b);
}

ll solve (ll a, ll b, ll m) {
    if (m == 1) {
        return 0;
    }
    if (b <= 1) {
        return qm(a, b, m);
    }
    ll tmp = solve(a, b-1, phi[m]);
    ll g = gcd(a, m);
    if (g == 1) {
        return qm(a, tmp, m);
    }
    else {
        if (check(a, b-1, phi[m])) {
            return qm(a, tmp, m);
        }
        else {
            return qm(a, tmp+phi[m], m);
        }
    }
}

int main () {
    int t;
    init();
    scanf("%d", &t);
    while (t--) {
        ll a, b, m;
        scanf("%lld %lld %lld", &a, &b, &m);
        cout << solve(a, b, m) << '\n';
    }
    return 0;
}

你可能感兴趣的:(数论)