P4139 上帝与集合的正确用法

P4139 上帝与集合的正确用法

题目大意

定义 \(a_0=1,a_n=2^{a_{n-1}}\),可以证明 \(a_n\bmod p\)\(n\) 足够大时为常数,求这个常数。

分析

利用了,扩展欧拉定理

  • \(b \geq \phi(p)\ a^b \equiv a^{b\ mod\ \phi(p)+\phi(p)}(mod\ p)\)
  • \(b < \phi(p)\ a^b \equiv a^{b\ mod\ \phi(p)}(mod\ p)\)

其中a,p可以不互质。

利用这个式子,可以快减少幂的大小。

接下来,我们递归的求出结果就好

时间复杂度\(O(\log^2 p)\)

Ac_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;

const int N = 1e7 + 10;

int n;
int phi[N],Primes[N],cnt;
bool st[N];
void get_eulers()
{
    phi[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!st[i]) Primes[cnt++]=i,phi[i]=i-1;
        for(int j=0;Primes[j]*i<N;j++)
        {
            st[Primes[j]*i]=1;
            if(i%Primes[j]==0)
            {
                phi[Primes[j]*i]=phi[i]*Primes[j];
                break;
            }
            else phi[i*Primes[j]]=phi[i]*(Primes[j]-1);
        }
    }
}

int ksm(int a,int b,int mod)
{
    int res = 1;
    while(b)
    {
        if(b&1) res = 1l*res*a%mod;
        b>>=1;
        a = 1ll*a*a%mod;
    }
    return res;
}

int get(int p)
{
    if(p==1) return 0;
    return ksm(2,get(phi[p])+phi[p],p);
}

int main()
{
    ios;
    get_eulers();
    int T;cin>>T;
    while(T--)
    {
        int p;cin>>p;
        cout<<get(p)<<'\n';
    }
    return 0;
}
posted @ 2022-09-06 17:41  艾特玖  阅读(26)  评论(0编辑  收藏  举报