幂塔问题 拓展欧拉定理 连续b个a的幂次模c 2019南京网络赛B

本文深入探讨了拓展欧拉定理在处理大规模幂运算中的应用,通过优化的算法实现快速求解连续幂次模运算的问题。文章详细介绍了算法的实现过程,包括预处理phi值、快速幂算法及递归求解策略。

拓展欧拉定理

问题描述

a^{a^{a^{...^{a}}}} mod$ $c (连续b个a的幂次)

#include <bits/stdc++.h>
#define FOR(i,s,t) for(int i=(s);i<=(t);i++)
#define ROF(i,s,t) for(int i=(s);i>=(t);i--)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define fi first
#define se second
#define endl '\n'
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e6 + 20;
const int N = 1e5 + 5;
const ll mod = 998244353;
const ll mod2 = 998244352;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int readInt(){
    int x=0;
    bool sign=false;
    char c=getchar();
    while(!isdigit(c)){
        sign=c=='-';
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return sign?-x:x;
}
ll readLong(){
    ll x=0;
    bool sign=false;
    char c=getchar();
    while(!isdigit(c)){
        sign=c=='-';
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return sign?-x:x;
}
string readString(){
    string s;
    char c=getchar();
    while(isspace(c)){
        c=getchar();
    }
    while(!isspace(c)){
        s+=c;
        c=getchar();
    }
    return s;
}

ll a, b, c;
ll mark[maxn], prime[maxn], phi[maxn];

ll mo(ll x, ll p){
    return x < p? x : (x % p +p);
}

ll fp(ll a, ll b, ll p){
	if (0 == b) return mo(1,p);
	ll t = mo(fp(a, b / 2, p) , p);
	if (b&1) return mo(mo(t * t , p) * a , p);
	else return mo(t * t , p);
}
void getphi(int N)
{
    int i,j, tot = 0;
    phi[1]=1;
    for(i=2;i<=N;i++){
        if(!mark[i]){
            prime[++tot]=i;
            phi[i]=i-1;
        }
        for(j=1;j<=tot;j++){
            if(i*prime[j]>N)  break;
            mark[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];break;
            }
            else  phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}

ll e[maxn];


ll dfs(int l, int r, ll mod){
    if (l == r || mod == 1) return e[l] % mod == 0 ? mod:(e[l] %mod);
    return fp(e[l], dfs(l+1,r,phi[mod]), mod);
}

int main()
{
    getphi(int(1e6 + 10));
    int tt = readInt();
    while(tt--){
        a = readLong();
        b = readLong();
        c = readLong();
        if(b == 0){
            printf("%lld\n", 1 % c);
            continue;
        }
        if (b == 1){
            printf("%lld\n", a % c);
            continue;
        }
        FOR(i,1,b) e[i] = a;
        printf("%lld\n", dfs(1,b,c)%c);
    }
    return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值