[扩展欧拉定理]luogu P4139 上帝与集合的正确用法

https://www.luogu.org/problem/P4139

 

分析

今天写了个毒瘤题,回来记录一下这个入门先

题目要求$2^{2^{2^{2^{...}}}} Mod\: p$

先说扩展欧拉定理

对于任意$a$大于等于$\varphi (p)$,有

$c^{a} Mod\: p=c^{a Mod\: \varphi (p)\: +\varphi (p)} Mod\: p$

如果$a$小于$p$则有

$c^{a} Mod\: p=c^{a Mod\: \varphi (p)} Mod\: p$

然后这题是无限指数,所以肯定满足a≥phi(p),所以直接递归到p=1的时候返回即可

用积性筛处理欧拉函数即可

 

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1e7+1;
int t,phi[N],p,prime[N],pcnt;
bool b[N];

void Prime() {
    phi[1]=1;
    for (int i=2;i<N;i++) {
        if (!b[i]) phi[i]=i-1,prime[++pcnt]=i;
        for (int j=1;j<=pcnt;j++) {
            if (prime[j]*i>=N) break;
            b[i*prime[j]]=1;
            if (i%prime[j]==0) {phi[i*prime[j]]=phi[i]*prime[j];break;}
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}

ll Pow(int x,int y,int p) {ll ans=1;for (;y;y>>=1,x=1ll*x*x%p) if (y&1) ans=ans*x%p; return ans;}

ll Solve(int p) {return p==1?0:Pow(2,Solve(phi[p])+phi[p],p);}

int main() {
    Prime();
    for (scanf("%d",&t);t;t--) {
        scanf("%d",&p);
        printf("%lld\n",Solve(p));
    }
}
View Code

 

posted @ 2019-10-14 19:35  Vagari  阅读(152)  评论(0编辑  收藏  举报