题解上帝与集合的正确用法

Posted h-lka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解上帝与集合的正确用法相关的知识,希望对你有一定的参考价值。

([题目链接](https://www.luogu.org/problem/P4139))

前置芝士 欧拉函数

题目大意:求(2^{2^{2^...}}) (mod) (p)的值。

第一眼看上去好像不可做的样纸,但是我们有一个定理:

(b>φ(p))时有(a^b equiv a^{b ext{ mod } varphi(p)+varphi(p)} ( ext{mod } p))

(b<φ(p))时,后面就不需要加(φ(p)).

那么这题可以看出一个递归雏形。我们可以用筛法将欧拉函数筛出来,筛到题目给的(p)的范围即可。

然后按照题意递归。最好有快速幂和龟速乘。

(Code:)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=1e7;
int T,p,phi[MAXN+10];
void Init(){
    phi[1]=1;
    for(int i=2;i<=MAXN;++i){
        if(!phi[i])
            for(int j=i;j<=MAXN;j+=i){
                if(!phi[j])phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
    }
}
inline int F_Mul(int a,int b,int m){
    int res=0;
    while(b){
        if(b&1)res=res+a,res%=m;
        b>>=1,a<<=1,a%=m;
    }
    return res;
}
inline int Fast(int a,int b,int m){
    int ans=1;
    while(b){
        if(b&1)ans=F_Mul(ans,a,m);
        b>>=1;a=F_Mul(a,a,m)%m;
    }
    return ans;
}
inline int solve(int p){
    if(p==1)return 0;
    return Fast(2,solve(phi[p])+phi[p],p);
}
int main(){
    Init();
    scanf("%d",&T);
    while(T--){
        scanf("%d",&p);
        printf("%d
",solve(p));
    }
    return 0;
}

以上是关于题解上帝与集合的正确用法的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3884: 上帝与集合的正确用法

BZOJ 3884 上帝与集合的正确用法

BZOJ3884 上帝与集合的正确用法 欧拉定理

bzoj3884: 上帝与集合的正确用法 扩展欧拉定理

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

[数学][广义欧拉定理]上帝与集合的正确用法