FZU 1759 Super A^B mod C(欧拉降幂 )

题目链接

解题思路

  欧拉降幂的模板题,因为C与A不一定互质,所以这里要用到广义欧拉降幂,用广义欧拉降幂的时候记得讨论指数与模数的大小关系。

线性筛选素数

bool u[maxn];
int p[maxn]; char b[maxn];
void pri() {
    for (int i = 2; i<maxn; ++i) {
        if (!u[i]) u[i] = p[++p[0]] = i;
        for (int j = 1; i*p[j]<maxn; ++j) {
            u[i*p[j]] = true;
            if (i%p[j]==0) break;
        }
    }
}

快速幂

ll solve(ll x, ll y, ll m) {
    ll res = x, ans = 1;
    while(y) {
        if (y&1) ans = ans*res%m;
        res = res*res%m;
        y >>= 1;
    }
    return ans;
}

如果指数小于模数的欧拉函数,则直接用快速幂求出答案。

    for (int i = 0; i<len; ++i) numb = numb*10 + b[i]-'0';
    printf("%lld
", solve(a, numb, c));

否则,求模数的欧拉函数并且进行降幂,然后快速幂求解

ll phi(ll num) {
    ll res = num;
    for (int i = 1; (ll)p[i]*p[i]<=num && i<=p[0]; ++i)
        if (num%p[i]==0) {
            while(num%p[i]==0) num /= p[i];
            res = res/p[i]*(p[i]-1);
        }
    if (num>1) res = res/num*(num-1);
    return res;
}
    ll phic = phi(c);
    for (int i = 0; i<len; ++i) numb = (numb*10 + b[i]-'0')%phic;
    printf("%lld
", solve(a, numb+phic, c));

完整代码

const int maxn = 1e6+10;
bool u[maxn];
int p[maxn]; char b[maxn];
void pri() {
    for (int i = 2; i<maxn; ++i) {
        if (!u[i]) u[i] = p[++p[0]] = i;
        for (int j = 1; i*p[j]<maxn; ++j) {
            u[i*p[j]] = true;
            if (i%p[j]==0) break;
        }
    }
}
ll phi(ll num) {
    ll res = num;
    for (int i = 1; (ll)p[i]*p[i]<=num && i<=p[0]; ++i)
        if (num%p[i]==0) {
            while(num%p[i]==0) num /= p[i];
            res = res/p[i]*(p[i]-1);
        }
    if (num>1) res = res/num*(num-1);
    return res;
}
ll solve(ll x, ll y, ll m) {
    ll res = x, ans = 1;
    while(y) {
        if (y&1) ans = ans*res%m;
        res = res*res%m;
        y >>= 1;
    }
    return ans;
}
int main(){
    pri(); ll a, c;
    while(~scanf("%lld%s%lld", &a, b, &c)) {
        int len = strlen(b); ll numb = 0;
        if (len>10) {
            ll phic = phi(c);
            for (int i = 0; i<len; ++i) numb = (numb*10 + b[i]-'0')%phic;
            printf("%lld
", solve(a, numb+phic, c));
        }
        else {
            for (int i = 0; i<len; ++i) numb = numb*10 + b[i]-'0';
            printf("%lld
", solve(a, numb, c));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12859474.html